summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiejunZhou <[email protected]>2023-04-18 18:11:20 +0800
committerGitHub <[email protected]>2023-04-18 18:11:20 +0800
commit23680f5e5f01702f7327160b8766bc893a5e6c54 (patch)
tree0cee1ec2d7e298bcfad386a76fde8870e58a72fb
parentd64ef2ab064047ab5aed15c7861e5a44ab8022e3 (diff)
Release ARMv7-M and ARMv8-M architecture ports (#249)
* Release ARMv7-M and ARMv8-M architecture ports * Add a pipeline to check ports_arch
-rw-r--r--.github/workflows/ports_arch_check.yml45
-rw-r--r--ports_arch/ARMv7-M/README.md5
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx.bat231
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx_sample.bat4
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/example_build/sample_threadx.c369
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s266
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/readme_threadx.txt208
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_restore.s83
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_save.s85
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_control.s77
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_disable.s77
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_restore.s75
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s325
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_stack_build.s131
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_system_return.s91
-rw-r--r--ports_arch/ARMv7-M/threadx/ac5/src/tx_timer_interrupt.s259
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/sample_threadx.c370
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S208
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.cproject150
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.project48
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/readme_threadx.txt209
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_misra.S723
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_restore.S88
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_save.S89
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_control.S85
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_disable.S85
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_restore.S82
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S331
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_stack_build.S139
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S99
-rw-r--r--ports_arch/ARMv7-M/threadx/ac6/src/tx_timer_interrupt.S261
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/example_build/sample_threadx.c369
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm232
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/inc/tx_el.h765
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/inc/tx_ghs.h77
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h406
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/readme_threadx.txt233
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_el.c1165
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_ghs.c485
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_ghse.c49
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_restore.arm78
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_save.arm80
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_control.arm73
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_disable.arm74
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_restore.arm73
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_schedule.arm291
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_stack_build.arm133
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_system_return.arm86
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/tx_timer_interrupt.arm241
-rw-r--r--ports_arch/ARMv7-M/threadx/ghs/src/txr_ghs.c84
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt18
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx.bat230
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx_sample.bat5
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_crt0.S91
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_vectors.S77
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.c370
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.ld125
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S205
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/readme_threadx.txt209
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_misra.S723
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_restore.S88
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_save.S86
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_control.S85
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_disable.S85
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_restore.S82
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S331
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_stack_build.S139
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S99
-rw-r--r--ports_arch/ARMv7-M/threadx/gnu/src/tx_timer_interrupt.S261
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/azure_rtos.eww13
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/cstartup_M.s72
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.c389
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewd2974
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewp2137
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.icf42
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp2752
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s151
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/readme_threadx.txt215
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c804
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_misra.s763
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_restore.s78
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_save.s80
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_control.s78
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_disable.s78
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_restore.s75
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s318
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_stack_build.s132
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s92
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/src/tx_timer_interrupt.s257
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/tx_low_power.c563
-rw-r--r--ports_arch/ARMv7-M/threadx/iar/tx_low_power.h58
-rw-r--r--ports_arch/ARMv7-M/threadx/inc/tx_port.h729
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_initialize.s109
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_thread_shell_entry.c174
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s646
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_thread_stack_build.s138
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_user_mode_entry.s88
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_initialize.S91
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_thread_shell_entry.c178
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S686
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/txm_module_manager_thread_stack_build.S139
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_alignment_adjust.c448
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_external_memory_enable.c297
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_handler.c110
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_notify.c84
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_mm_register_setup.c860
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/gnu/module_lib/src/txm_module_thread_shell_entry.c173
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S687
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/txm_module_manager_thread_stack_build.s139
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/iar/module_lib/src/txm_module_thread_shell_entry.c173
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c804
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_misra.s763
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s673
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/txm_module_manager_thread_stack_build.s138
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h732
-rw-r--r--ports_arch/ARMv7-M/threadx_modules/inc/txm_module_port.h469
-rw-r--r--ports_arch/ARMv8-M/README.md5
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt21
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt228
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S283
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_misra.S723
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_restore.S89
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_save.S89
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_control.S87
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_disable.S88
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_restore.S85
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S399
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack.c592
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_allocate.S90
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_free.S88
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_initialize.S88
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_stack_build.S145
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S101
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/tx_timer_interrupt.S248
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_allocate.c119
-rw-r--r--ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_free.c120
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt21
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt210
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S283
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_misra.S723
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_restore.S89
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_save.S89
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_control.S87
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_disable.S88
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_restore.S85
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S396
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack.c596
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_allocate.S90
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_free.S88
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_initialize.S88
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_stack_build.S145
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S101
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/tx_timer_interrupt.S248
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_allocate.c119
-rw-r--r--ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_free.c120
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt221
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c804
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s237
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_misra.s763
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_restore.s77
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_save.s77
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_control.s78
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_disable.s78
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_restore.s75
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s383
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack.c597
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_allocate.s80
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_free.s78
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_initialize.s78
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_stack_build.s135
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s91
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/tx_timer_interrupt.s251
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_allocate.c119
-rw-r--r--ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_free.c120
-rw-r--r--ports_arch/ARMv8-M/threadx/inc/tx_port.h658
-rw-r--r--ports_arch/ARMv8-M/threadx/inc/tx_secure_interface.h61
-rwxr-xr-xscripts/copy_armv7_m.sh80
-rwxr-xr-xscripts/copy_armv8_m.sh104
-rwxr-xr-xscripts/copy_module_armv7_m.sh64
179 files changed, 47913 insertions, 0 deletions
diff --git a/.github/workflows/ports_arch_check.yml b/.github/workflows/ports_arch_check.yml
new file mode 100644
index 00000000..bc6d5440
--- /dev/null
+++ b/.github/workflows/ports_arch_check.yml
@@ -0,0 +1,45 @@
+# This is a basic workflow to help you get started with Actions
+
+name: ports_arch_check
+
+# Controls when the action will run. Triggers the workflow on push or pull request
+# events but only for the master branch
+on:
+ pull_request:
+ branches: [ master ]
+ paths:
+ - ".github/workflows/ports_arch_check.yml"
+ - 'common/**'
+ - 'common_modules/**'
+ - 'common_smp/**'
+ - 'ports/**'
+ - 'ports_modules/**'
+ - 'ports_smp/**'
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+ # This workflow contains a single job called "build"
+ build:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ # Steps represent a sequence of tasks that will be executed as part of the job
+ steps:
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - name: Checkout sources recursively
+ uses: actions/checkout@v2
+ with:
+ token: ${{ secrets.REPO_SCOPED_TOKEN }}
+ submodules: true
+
+ # Copy ports arch
+ - name: Copy ports arch
+ run: |
+ scripts/copy_armv7_m.sh && scripts/copy_armv8_m.sh && scripts/copy_module_armv7_m.sh
+ if [[ -n $(git status --porcelain) ]]; then
+ echo "Ports for ARM architecture is not updated"
+ exit 1
+ fi
+
+
+
diff --git a/ports_arch/ARMv7-M/README.md b/ports_arch/ARMv7-M/README.md
new file mode 100644
index 00000000..19863cdb
--- /dev/null
+++ b/ports_arch/ARMv7-M/README.md
@@ -0,0 +1,5 @@
+# ARMv7-M architecture ports
+
+The ThreadX, ThreadX SMP, ThreadX Modules and ThreadX SMP Modules ports for ARMv7 share many files in common.
+To make work more efficient these files are internally tracked only once and copied over to specific ports for users.
+
diff --git a/ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx.bat b/ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx.bat
new file mode 100644
index 00000000..686a3e0f
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx.bat
@@ -0,0 +1,231 @@
+del tx.a
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork tx_initialize_low_level.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_stack_build.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_schedule.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_system_return.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_context_save.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_context_restore.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_interrupt_control.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_interrupt_disable.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_thread_interrupt_restore.s
+armasm -g --cpu=cortex-m4 --cpreproc --fpu=vfpv3 --apcs=interwork ../src/tx_timer_interrupt.s
+
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_allocate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_cleanup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_release.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_allocate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_cleanup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_search.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_release.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_cleanup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_set.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_set_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_high_level.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_kernel_enter.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_kernel_setup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_cleanup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_priority_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_put.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_cleanup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_flush.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_front_send.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_receive.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_send.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_send_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_ceiling_put.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_cleanup.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_put.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_put_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_entry_exit_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_identify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_preemption_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_priority_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_relinquish.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_reset.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_resume.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_shell_entry.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_sleep.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_analyze.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_error_handler.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_error_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_suspend.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_preempt_check.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_resume.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_suspend.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_terminate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_time_slice.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_time_slice_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_timeout.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_wait_abort.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_time_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_time_set.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_activate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_deactivate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_expiration_process.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_performance_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_performance_system_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_system_activate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_system_deactivate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_thread_entry.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_buffer_full_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_enable.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_event_filter.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_event_unfilter.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_disable.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_initialize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_interrupt_control.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_isr_enter_insert.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_isr_exit_insert.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_object_register.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_object_unregister.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_user_event_insert.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_allocate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_release.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_allocate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_release.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_set.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_set_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_put.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_flush.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_front_send.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_receive.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_send.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_send_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_ceiling_put.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_prioritize.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_put.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_put_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_entry_exit_notify.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_info_get.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_preemption_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_priority_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_relinquish.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_reset.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_resume.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_suspend.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_terminate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_time_slice_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_wait_abort.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_activate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_change.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_create.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_deactivate.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_delete.c
+armcc -g --cpu=cortex-m4 --fpu=vfpv3 -Otime -O2 -Odiv -c --data_reorder -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_info_get.c
+armar --create 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
+armar -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o tx_thread_interrupt_restore.o
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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
+armar -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_arch/ARMv7-M/threadx/ac5/example_build/build_threadx_sample.bat b/ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx_sample.bat
new file mode 100644
index 00000000..420ab366
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx_sample.bat
@@ -0,0 +1,4 @@
+armasm -g --cpu=cortex-m4 --cpreproc --apcs=interwork tx_initialize_low_level.s
+armcc -c -g --cpu=cortex-m4 -O2 -I../../../../common/inc -I../../inc sample_threadx.c
+armlink -d -o sample_threadx.axf --elf --map --ro-base=0x00000000 --rw-base=0x20000000 --first __tx_vectors --datacompressor=off --inline --info=inline --callgraph --list sample_threadx.map tx_initialize_low_level.o sample_threadx.o tx.a
+
diff --git a/ports_arch/ARMv7-M/threadx/ac5/example_build/sample_threadx.c b/ports_arch/ARMv7-M/threadx/ac5/example_build/sample_threadx.c
new file mode 100644
index 00000000..418ec634
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/sample_threadx.c
@@ -0,0 +1,369 @@
+/* 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 "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;
+
+
+/* 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", first_unused_memory, 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;
+ }
+}
+
+
+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_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s
new file mode 100644
index 00000000..0a9bb7b6
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s
@@ -0,0 +1,266 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_system_stack_ptr
+ IMPORT _tx_initialize_unused_memory
+ IMPORT _tx_thread_context_save
+ IMPORT _tx_thread_context_restore
+#ifndef TX_NO_TIMER
+ IMPORT _tx_timer_interrupt
+#endif
+ IMPORT __main
+ IMPORT |Image$$RO$$Limit|
+ IMPORT |Image$$RW$$Base|
+ IMPORT |Image$$ZI$$Base|
+ IMPORT |Image$$ZI$$Limit|
+ IMPORT PendSV_Handler
+
+
+SYSTEM_CLOCK EQU 6000000
+SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 100) -1)
+
+
+/* Setup the stack and heap areas. */
+
+STACK_SIZE EQU 0x00000400
+HEAP_SIZE EQU 0x00000000
+
+ AREA STACK, NOINIT, READWRITE, ALIGN=3
+StackMem
+ SPACE STACK_SIZE
+__initial_sp
+
+
+ AREA HEAP, NOINIT, READWRITE, ALIGN=3
+__heap_base
+HeapMem
+ SPACE HEAP_SIZE
+__heap_limit
+
+
+ AREA RESET, CODE, READONLY
+
+ EXPORT __tx_vectors
+__tx_vectors
+ DCD __initial_sp // Reset and system stack ptr
+ DCD Reset_Handler // Reset goes to startup function
+ DCD __tx_NMIHandler // NMI
+ DCD __tx_BadHandler // HardFault
+ DCD 0 // MemManage
+ DCD 0 // BusFault
+ DCD 0 // UsageFault
+ DCD 0 // 7
+ DCD 0 // 8
+ DCD 0 // 9
+ DCD 0 // 10
+ DCD __tx_SVCallHandler // SVCall
+ DCD __tx_DBGHandler // Monitor
+ DCD 0 // 13
+ DCD PendSV_Handler // PendSV
+#ifndef TX_NO_TIMER
+ DCD __tx_SysTickHandler // SysTick
+#else
+ DCD 0 // SysTick
+#endif
+ DCD __tx_IntHandler // Int 0
+ DCD __tx_IntHandler // Int 1
+ DCD __tx_IntHandler // Int 2
+ DCD __tx_IntHandler // Int 3
+
+
+ AREA ||.text||, CODE, READONLY
+ EXPORT Reset_Handler
+Reset_Handler
+ CPSID i
+#ifdef __TARGET_FPU_VFP
+ LDR r0, =0xE000ED88 // Pickup address of CPACR
+ LDR r1, [r0] // Pickup CPACR
+ MOV32 r2, 0x00F00000 // Build enable value
+ ORR r1, r1, r2 // Or in enable value
+ STR r1, [r0] // Setup CPACR
+#endif
+ LDR r0, =__main
+ BX r0
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mx/AC5 */
+/* 6.1.10 */
+/* 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ EXPORT _tx_initialize_low_level
+_tx_initialize_low_level
+
+ /* Ensure that interrupts are disabled. */
+ CPSID i
+
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ LDR r1, =|Image$$ZI$$Limit| // Build first free address
+ ADD r1, r1, #4 // Add 4 to get to next free word
+ STR r1, [r0] // Setup first unused memory pointer
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =__tx_vectors // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =__tx_vectors // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+#ifndef TX_NO_TIMER
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+#endif
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+
+/* Define initial heap/stack routine for the ARM RVCT startup code.
+ This routine will set the initial stack and heap locations */
+
+ EXPORT __user_initial_stackheap
+__user_initial_stackheap
+ LDR r0, =HeapMem
+ LDR r1, =(StackMem + STACK_SIZE)
+ LDR r2, =(HeapMem + HEAP_SIZE)
+ LDR r3, =StackMem
+ BX lr
+
+
+/* Define shells for each of the unused vectors. */
+
+ EXPORT __tx_BadHandler
+__tx_BadHandler
+ B __tx_BadHandler
+
+ EXPORT __tx_SVCallHandler
+__tx_SVCallHandler
+ B __tx_SVCallHandler
+
+ EXPORT __tx_IntHandler
+__tx_IntHandler
+// VOID InterruptHandler (VOID)
+// {
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ /* Do interrupt handler work here */
+ /* .... */
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+
+#ifndef TX_NO_TIMER
+ EXPORT __tx_SysTickHandler
+__tx_SysTickHandler
+// VOID TimerInterruptHandler (VOID)
+// {
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+#endif
+
+ EXPORT __tx_NMIHandler
+__tx_NMIHandler
+ B __tx_NMIHandler
+
+ EXPORT __tx_DBGHandler
+__tx_DBGHandler
+ B __tx_DBGHandler
+
+ ALIGN
+ LTORG
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/readme_threadx.txt b/ports_arch/ARMv7-M/threadx/ac5/readme_threadx.txt
new file mode 100644
index 00000000..b7b7cee9
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/readme_threadx.txt
@@ -0,0 +1,208 @@
+ Microsoft's Azure RTOS ThreadX for ARMv7-M
+ (Cortex-M3, Cortex-M4, Cortex-M7)
+ Using ARM Compiler 5 (AC5)
+
+
+1. Building the ThreadX run-time Library
+
+Navigate to the "example_build" directory. Ensure that
+you have setup your path and other environment variables necessary for the AC5
+compiler. At this point you may run the build_threadx.bat batch file. This will
+build the ThreadX run-time environment in the "example_build" directory.
+
+You should observe assembly and compilation of a series of ThreadX source
+files. At the end of the batch file, they are all combined into the
+run-time library file: tx.a. This file must be linked with your
+application in order to use ThreadX.
+
+
+2. Demonstration System
+
+The ThreadX demonstration is designed to execute under the ARM DS Cortex-M
+simulator.
+
+Building the demonstration is easy; simply execute the build_threadx_sample.bat
+batch file while inside the "example_build" directory.
+
+You should observe the compilation of sample_threadx.c (which is the demonstration
+application) and linking with tx.a. The resulting file sample_threadx.axf
+is a binary file that can be downloaded and executed on the ARM DS Cortex-M
+simulator.
+
+
+3. System Initialization
+
+The entry point in ThreadX for the Cortex-M using AC5 tools is at label
+__main. This is defined within the AC5 compiler's startup code. In
+addition, this is where all static and global pre-set C variable
+initialization processing takes place.
+
+The ThreadX tx_initialize_low_level.s file is responsible for setting up
+various system data structures, the vector area, and a periodic timer interrupt
+source.
+
+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.
+
+
+4. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-M version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+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 it run faster, you can change the ThreadX library
+project to enable various compiler 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.
+
+
+6. Interrupt Handling
+
+ThreadX provides complete and high-performance interrupt handling for Cortex-M
+targets. There are a certain set of requirements that are defined in the
+following sub-sections:
+
+
+6.1 Vector Area
+
+The Cortex-M vectors start at the label __tx_vectors. The application may modify
+the vector area according to its needs.
+
+
+6.2 Managed Interrupts
+
+ISRs for Cortex-M can be written completely in C (or assembly language) without any
+calls to _tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed
+access to the ThreadX API that is available to ISRs.
+
+ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
+
+void your_C_isr(void)
+{
+
+ /* ISR processing goes here, including any needed function calls. */
+}
+
+ISRs written in assembly language will take the form:
+
+ EXPORT your_assembly_isr
+your_assembly_isr
+
+ PUSH {r0, lr}
+
+ ; ISR processing goes here, including any needed function calls.
+
+ POP {r0, lr}
+ BX lr
+
+
+7. FPU Support
+
+ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context - no additional setup by the application.
+
+
+8. 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:
+
+06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using AC5 tools.
+
+
+Copyright(c) 1996-2021 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_restore.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_restore.s
new file mode 100644
index 00000000..00c88632
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_restore.s
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ IMPORT _tx_execution_isr_exit
+#endif
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ EXPORT _tx_thread_context_restore
+_tx_thread_context_restore
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ ALIGN
+ LTORG
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_save.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_save.s
new file mode 100644
index 00000000..e7913e7d
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_save.s
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ IMPORT _tx_execution_isr_enter
+#endif
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ EXPORT _tx_thread_context_save
+_tx_thread_context_save
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ /* Context is already saved - just return. */
+
+ BX lr
+// }
+ ALIGN
+ LTORG
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_control.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_control.s
new file mode 100644
index 00000000..657ed26b
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_control.s
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ EXPORT _tx_thread_interrupt_control
+_tx_thread_interrupt_control
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_disable.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_disable.s
new file mode 100644
index 00000000..34708d62
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_disable.s
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ EXPORT _tx_thread_interrupt_disable
+_tx_thread_interrupt_disable
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_restore.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_restore.s
new file mode 100644
index 00000000..2415032d
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_interrupt_restore.s
@@ -0,0 +1,75 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ EXPORT _tx_thread_interrupt_restore
+_tx_thread_interrupt_restore
+
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s
new file mode 100644
index 00000000..c5dc3a2e
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s
@@ -0,0 +1,325 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_execute_ptr
+ IMPORT _tx_timer_time_slice
+ IMPORT _tx_thread_system_stack_ptr
+ IMPORT _tx_thread_preempt_disable
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ IMPORT _tx_execution_thread_enter
+ IMPORT _tx_execution_thread_exit
+#endif
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/AC5 */
+/* 6.1.11 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ EXPORT _tx_thread_schedule
+_tx_thread_schedule
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+
+#ifdef __TARGET_FPU_VFP
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ EXPORT __tx_PendSVHandler
+ EXPORT PendSV_Handler
+__tx_PendSVHandler
+PendSV_Handler
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __TARGET_FPU_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __TARGET_FPU_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+#ifdef __TARGET_FPU_VFP
+ EXPORT tx_thread_fpu_enable
+tx_thread_fpu_enable
+ EXPORT tx_thread_fpu_disable
+tx_thread_fpu_disable
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+ EXPORT _tx_vfp_access
+_tx_vfp_access
+ VMOV.F32 s0, s0 // Simply access the VFP
+ BX lr // Return to caller
+
+#endif
+
+ ALIGN
+ LTORG
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_stack_build.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_stack_build.s
new file mode 100644
index 00000000..6f1c452f
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_stack_build.s
@@ -0,0 +1,131 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ EXPORT _tx_thread_stack_build
+_tx_thread_stack_build
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_system_return.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_system_return.s
new file mode 100644
index 00000000..0feb88c6
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_system_return.s
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mx/AC5 */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ EXPORT _tx_thread_system_return
+_tx_thread_system_return
+
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_timer_interrupt.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_timer_interrupt.s
new file mode 100644
index 00000000..ab23bebf
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_timer_interrupt.s
@@ -0,0 +1,259 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_timer_time_slice
+ IMPORT _tx_timer_system_clock
+ IMPORT _tx_timer_current_ptr
+ IMPORT _tx_timer_list_start
+ IMPORT _tx_timer_list_end
+ IMPORT _tx_timer_expired_time_slice
+ IMPORT _tx_timer_expired
+ IMPORT _tx_thread_time_slice
+ IMPORT _tx_timer_expiration_process
+ IMPORT _tx_thread_preempt_disable
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_execute_ptr
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mx/AC5 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+#ifndef TX_NO_TIMER
+ EXPORT _tx_timer_interrupt
+_tx_timer_interrupt
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired
+
+ STMDB sp!, {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice
+
+ // }
+
+__tx_timer_not_ts_expiration
+
+ LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+#endif
+ ALIGN
+ LTORG
+ END
diff --git a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/sample_threadx.c b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/sample_threadx.c
new file mode 100644
index 00000000..597f373c
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/sample_threadx.c
@@ -0,0 +1,370 @@
+/* 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 "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;
+ }
+}
+
+
+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_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S
new file mode 100644
index 00000000..3d1922b3
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S
@@ -0,0 +1,208 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .global _tx_thread_system_stack_ptr
+ .global _tx_initialize_unused_memory
+#ifndef TX_NO_TIMER
+ .global _tx_timer_interrupt
+ .global __tx_SysTickHandler // SysTick
+#endif
+ .global __main
+ .global __tx_SVCallHandler
+ .global __tx_PendSVHandler
+ .global __tx_NMIHandler // NMI
+ .global __tx_BadHandler // HardFault
+ .global __tx_SVCallHandler // SVCall
+ .global __tx_DBGHandler // Monitor
+ .global __tx_PendSVHandler // PendSV
+
+ .global __tx_IntHandler // Int 0
+
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mx/AC6 */
+/* 6.1.10 */
+/* 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ .global _tx_initialize_low_level
+ .thumb_func
+_tx_initialize_low_level:
+
+ /* Ensure that interrupts are disabled. */
+ CPSID i
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ LDR r1, =Image$$ARM_LIB_STACKHEAP$$ZI$$Limit // Build first free address
+ ADD r1, r1, #4 //
+ STR r1, [r0] // Setup first unused memory pointer
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =vector_table // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =vector_table // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+#ifndef TX_NO_TIMER
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+#endif
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+/* Define shells for each of the unused vectors. */
+ .global __tx_BadHandler
+ .thumb_func
+__tx_BadHandler:
+ B __tx_BadHandler
+
+/* added to catch the hardfault */
+ .global __tx_HardfaultHandler
+ .thumb_func
+__tx_HardfaultHandler:
+ B __tx_HardfaultHandler
+
+/* added to catch the SVC */
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_SVCallHandler:
+ B __tx_SVCallHandler
+
+/* Generic interrupt handler template */
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+// VOID InterruptHandler (VOID)
+// {
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ /* Do interrupt handler work here */
+ /* BL <your C Function>.... */
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+
+#ifndef TX_NO_TIMER
+/* System Tick timer interrupt handler */
+ .global __tx_SysTickHandler
+ .global SysTick_Handler
+ .thumb_func
+__tx_SysTickHandler:
+ .thumb_func
+SysTick_Handler:
+// VOID SysTick_Handler (VOID)
+// {
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+#endif
+
+/* NMI, DBG handlers */
+ .global __tx_NMIHandler
+ .thumb_func
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+ .global __tx_DBGHandler
+ .thumb_func
+__tx_DBGHandler:
+ B __tx_DBGHandler
diff --git a/ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.cproject b/ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.cproject
new file mode 100644
index 00000000..b7df20f1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.cproject
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+
+ <cconfiguration id="com.arm.eclipse.build.config.v6.lib.debug.base.1507005551">
+
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.1507005551" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+
+ <externalSettings/>
+
+ <extensions>
+
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ </extensions>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.debug.base.1507005551" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug.base">
+
+ <folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.1507005551." name="/" resourcePath="">
+
+ <toolChain id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.1022814766" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6">
+
+ <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.688166309" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-M7.FPv5_D16" valueType="string"/>
+
+ <option id="com.arm.toolchain.v6.base.options.floatabi.197203083" name="Float ABI" superClass="com.arm.toolchain.v6.base.options.floatabi" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.floatabi.hard" valueType="enumerated"/>
+
+ <option id="com.arm.toolchain.v6.base.options.inst.552700328" name="Instruction set" superClass="com.arm.toolchain.v6.base.options.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.inst.thumb" valueType="enumerated"/>
+
+ <option id="com.arm.toolchain.v6.base.options.debug.level.1623863720" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
+
+ <targetPlatform id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.1022814766.195306460" name=""/>
+
+ <builder autoBuildTarget="all" buildPath="${workspace_loc:/tx}/Debug" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.arm.toolchain.v6.builder.1164059605" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.toolchain.v6.builder"/>
+
+ <tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.100103692" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6">
+
+ <option id="com.arm.tool.c.compiler.v6.base.option.target.775437314" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="arm-arm-none-eabi" valueType="string"/>
+
+ <option id="com.arm.tool.c.compiler.v6.base.option.cpu.957518664" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-m7" valueType="string"/>
+
+ <option id="com.arm.tool.c.compiler.v6.base.option.fpu.1476959906" name="FPU (-mfpu)" superClass="com.arm.tool.c.compiler.v6.base.option.fpu" useByScannerDiscovery="true" value="fpv5-d16" valueType="string"/>
+
+ <option id="com.arm.tool.c.compiler.v6.base.option.floatabi.2113301488" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.c.compiler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.hard" valueType="enumerated"/>
+
+ <option id="com.arm.tool.c.compiler.v6.base.option.inst.36110020" name="Instruction set" superClass="com.arm.tool.c.compiler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.thumb" valueType="enumerated"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.compiler.v6.base.option.incpath.1498990421" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc_generic}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc_port}&quot;"/>
+
+ </option>
+
+ <option id="com.arm.tool.c.compiler.v6.base.options.debug.level.536480260" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="com.arm.tool.c.compiler.v6.base.option.flags.694010683" name="Other flags" superClass="com.arm.tool.c.compiler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList"/>
+
+ <inputType id="com.arm.tool.c.compiler.v6.base.input.1961882835" superClass="com.arm.tool.c.compiler.v6.base.input"/>
+
+ </tool>
+
+ <tool id="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6.262825882" name="Arm C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6">
+
+ <option id="com.arm.tool.c.compiler.v6.base.options.debug.level.1390685682" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
+
+ </tool>
+
+ <tool id="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6.596919840" name="Arm Assembler 6" superClass="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6">
+
+ <option id="com.arm.tool.assembler.v6.base.option.target.1155866423" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" useByScannerDiscovery="false" value="arm-arm-none-eabi" valueType="string"/>
+
+ <option id="com.arm.tool.assembler.v6.base.option.cpu.1741335442" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-m7" valueType="string"/>
+
+ <option id="com.arm.tool.assembler.v6.base.option.fpu.169397194" name="FPU (-mfpu)" superClass="com.arm.tool.assembler.v6.base.option.fpu" useByScannerDiscovery="true" value="fpv5-d16" valueType="string"/>
+
+ <option id="com.arm.tool.assembler.v6.base.option.floatabi.1378563076" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.assembler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.hard" valueType="enumerated"/>
+
+ <option id="com.arm.tool.assembler.v6.base.option.inst.213408634" name="Instruction set" superClass="com.arm.tool.assembler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.thumb" valueType="enumerated"/>
+
+ <option id="com.arm.tool.assembler.v6.base.options.debug.level.383141003" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" value="com.arm.tool.assembler.v6.base.options.debug.level.std" valueType="enumerated"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="com.arm.tool.assembler.v6.base.option.flags.982140214" name="Other flags" superClass="com.arm.tool.assembler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList"/>
+
+ <inputType id="com.arm.tool.assembler.v6.base.input.1847017761" superClass="com.arm.tool.assembler.v6.base.input"/>
+
+ </tool>
+
+ <tool id="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6.1124663047" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6"/>
+
+ <tool id="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6.1439633481" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6"/>
+
+ </toolChain>
+
+ </folderInfo>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+
+ </cconfiguration>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <project id="tx.com.arm.eclipse.build.project.v6.lib.1408735755" name="Static Library"/>
+
+ </storageModule>
+
+ <storageModule moduleId="scannerConfiguration">
+
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+
+ <storageModule moduleId="refreshScope" versionNumber="2">
+
+ <configuration configurationName="Debug">
+
+ <resource resourceType="PROJECT" workspacePath="/tx"/>
+
+ </configuration>
+
+ <configuration configurationName="Release">
+
+ <resource resourceType="PROJECT" workspacePath="/tx"/>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
+
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+
+</cproject>
diff --git a/ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.project b/ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.project
new file mode 100644
index 00000000..863ca5cb
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.project
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>tx</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>inc_generic</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/inc</locationURI>
+ </link>
+ <link>
+ <name>inc_port</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-2-PROJECT_LOC%7D/inc</locationURI>
+ </link>
+ <link>
+ <name>src_generic</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/src</locationURI>
+ </link>
+ <link>
+ <name>src_port</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-2-PROJECT_LOC%7D/src</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/ports_arch/ARMv7-M/threadx/ac6/readme_threadx.txt b/ports_arch/ARMv7-M/threadx/ac6/readme_threadx.txt
new file mode 100644
index 00000000..d98c90cb
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/readme_threadx.txt
@@ -0,0 +1,209 @@
+ Microsoft's Azure RTOS ThreadX for ARMv7-M
+ (Cortex-M3, Cortex-M4, Cortex-M7)
+ Using ARM Compiler 6 (AC6)
+
+
+1. Building the ThreadX run-time Library
+
+In order to build the ThreadX library and the ThreadX demonstration, first import
+the 'tx' and 'sample_threadx' projects (located in the "example_build" directory)
+into your DS workspace.
+
+Building the ThreadX library is easy; simply right-click the Eclipse project
+"tx" and then select the "Build Project" button. You should now observe the compilation
+and assembly of the ThreadX library. This project build produces the ThreadX
+library file tx.a.
+
+
+2. Demonstration System
+
+The ThreadX demonstration is designed to execute under the DS debugger on the
+MPS2_Cortex_Mx Bare Metal simulator.
+
+Building the demonstration is easy; simply right-click the Eclipse project
+"sample_threadx" and then select the "Build Project" button. You should now observe
+the compilation and assembly of the ThreadX demonstration. This project build produces
+the ThreadX library file sample_threadx.axf. Next, expand the demo ThreadX project folder
+in the Project Explorer window, right-click on the 'cortex-mx_tx.launch' file, click
+'Debug As', and then click 'cortex-mx_tx' from the submenu. This will cause the
+debugger to load the sample_threadx.axf ELF file and run to main. You are now ready
+to execute the ThreadX demonstration.
+
+
+3. System Initialization
+
+The entry point in ThreadX for the Cortex-M using AC6 tools uses the standard GNU
+Cortex-M reset sequence. From the reset vector the C runtime will be initialized.
+
+The ThreadX tx_initialize_low_level.S file is responsible for setting up
+various system data structures, the vector area, and a periodic timer interrupt
+source.
+
+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.
+
+
+4. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-M version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+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 it run faster, you can change the ThreadX library
+project to enable various compiler 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.
+
+
+6. Interrupt Handling
+
+ThreadX provides complete and high-performance interrupt handling for Cortex-M
+targets. There are a certain set of requirements that are defined in the
+following sub-sections:
+
+
+6.1 Vector Area
+
+The Cortex-M vectors start at the label __tx_vectors or similar. The application may modify
+the vector area according to its needs. There is code in tx_initialize_low_level() that will
+configure the vector base register.
+
+
+6.2 Managed Interrupts
+
+A ThreadX managed interrupt is defined below. By following these conventions, the
+application ISR is then allowed access to various ThreadX services from the ISR.
+Here is the standard template for managed ISRs in ThreadX:
+
+
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+; VOID InterruptHandler (VOID)
+; {
+ PUSH {r0, lr}
+
+; /* Do interrupt handler work here */
+; /* BL <your interrupt routine in C> */
+
+ POP {r0, lr}
+ BX lr
+; }
+
+
+Note: the Cortex-M requires exception handlers to be thumb labels, this implies bit 0 set.
+To accomplish this, the declaration of the label has to be preceded by the assembler directive
+.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
+be inserted in the correct location in the interrupt vector table. This table is typically
+located in either your runtime startup file or in the tx_initialize_low_level.S file.
+
+
+7. FPU Support
+
+ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context - no additional setup by the application.
+
+
+8. 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:
+
+06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using AC6 tools.
+
+
+Copyright(c) 1996-2021 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_misra.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_misra.S
new file mode 100644
index 00000000..c84d8576
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_misra.S
@@ -0,0 +1,723 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ #define SHT_PROGBITS 0x1
+
+ .global __aeabi_memset
+ .global _tx_thread_current_ptr
+ .global _tx_thread_interrupt_disable
+ .global _tx_thread_interrupt_restore
+ .global _tx_thread_stack_analyze
+ .global _tx_thread_stack_error_handler
+ .global _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_trace_buffer_current_ptr
+ .global _tx_trace_buffer_end_ptr
+ .global _tx_trace_buffer_start_ptr
+ .global _tx_trace_event_enable_bits
+ .global _tx_trace_full_notify_function
+ .global _tx_trace_header_ptr
+#endif
+
+ .global _tx_misra_always_true
+ .global _tx_misra_block_pool_to_uchar_pointer_convert
+ .global _tx_misra_byte_pool_to_uchar_pointer_convert
+ .global _tx_misra_char_to_uchar_pointer_convert
+ .global _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_indirect_void_to_uchar_pointer_convert
+ .global _tx_misra_memset
+ .global _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_object_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_pointer_to_ulong_convert
+ .global _tx_misra_status_get
+ .global _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_time_stamp_get
+#endif
+ .global _tx_misra_timer_indirect_to_void_pointer_convert
+ .global _tx_misra_timer_pointer_add
+ .global _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_trace_event_insert
+#endif
+ .global _tx_misra_uchar_pointer_add
+ .global _tx_misra_uchar_pointer_dif
+ .global _tx_misra_uchar_pointer_sub
+ .global _tx_misra_uchar_to_align_type_pointer_convert
+ .global _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_entry_pointer_convert
+ .global _tx_misra_uchar_to_header_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ .global _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_object_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_void_pointer_convert
+ .global _tx_misra_ulong_pointer_add
+ .global _tx_misra_ulong_pointer_dif
+ .global _tx_misra_ulong_pointer_sub
+ .global _tx_misra_ulong_to_pointer_convert
+ .global _tx_misra_ulong_to_thread_pointer_convert
+ .global _tx_misra_user_timer_pointer_get
+ .global _tx_misra_void_to_block_pool_pointer_convert
+ .global _tx_misra_void_to_byte_pool_pointer_convert
+ .global _tx_misra_void_to_event_flags_pointer_convert
+ .global _tx_misra_void_to_indirect_uchar_pointer_convert
+ .global _tx_misra_void_to_mutex_pointer_convert
+ .global _tx_misra_void_to_queue_pointer_convert
+ .global _tx_misra_void_to_semaphore_pointer_convert
+ .global _tx_misra_void_to_thread_pointer_convert
+ .global _tx_misra_void_to_uchar_pointer_convert
+ .global _tx_misra_void_to_ulong_pointer_convert
+ .global _tx_misra_ipsr_get
+ .global _tx_misra_control_get
+ .global _tx_misra_control_set
+#ifdef __ARM_FP
+ .global _tx_misra_fpccr_get
+ .global _tx_misra_vfp_touch
+#endif
+
+ .global _tx_misra_event_flags_group_not_used
+ .global _tx_misra_event_flags_set_notify_not_used
+ .global _tx_misra_queue_not_used
+ .global _tx_misra_queue_send_notify_not_used
+ .global _tx_misra_semaphore_not_used
+ .global _tx_misra_semaphore_put_notify_not_used
+ .global _tx_misra_thread_entry_exit_notify_not_used
+ .global _tx_misra_thread_not_used
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+ .syntax unified
+ .thumb_func
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ .text
+ .thumb_func
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N _tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N _tx_misra_message_copy_1
+_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N _tx_misra_message_copy_2
+_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR R2,=0x54485244
+ CMP R1,R2
+ BNE.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_3
+_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N _tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N _tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N _tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N _tx_misra_trace_event_insert_4
+ LDR.N R0,DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N _tx_misra_trace_event_insert_0
+_tx_misra_trace_event_insert_4:
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ .data
+DataTable2_1:
+ .word _tx_trace_buffer_current_ptr
+
+ .data
+DataTable2_2:
+ .word _tx_trace_event_enable_bits
+
+ .data
+DataTable2_5:
+ .word _tx_trace_buffer_end_ptr
+
+ .data
+DataTable2_6:
+ .word _tx_trace_buffer_start_ptr
+
+ .data
+DataTable2_7:
+ .word _tx_trace_header_ptr
+
+ .data
+DataTable2_8:
+ .word _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ .data
+DataTable2_3:
+ .word _tx_thread_system_state
+
+ .data
+DataTable2_4:
+ .word _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARM_FP
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ .data
+ .word 0
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_restore.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..a6ce499a
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_restore.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_exit
+#endif
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .global _tx_thread_context_restore
+ .thumb_func
+_tx_thread_context_restore:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_save.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_save.S
new file mode 100644
index 00000000..eb58634c
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_save.S
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text
+ .align 4
+ .syntax unified
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_enter
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ .global _tx_thread_context_save
+ .thumb_func
+_tx_thread_context_save:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ /* Context is already saved - just return. */
+
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_control.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..375f7280
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_control.S
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ .global _tx_thread_interrupt_control
+ .thumb_func
+_tx_thread_interrupt_control:
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_disable.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_disable.S
new file mode 100644
index 00000000..33917aa6
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_disable.S
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ .global _tx_thread_interrupt_disable
+ .thumb_func
+_tx_thread_interrupt_disable:
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_restore.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_restore.S
new file mode 100644
index 00000000..3f55f3b4
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_interrupt_restore.S
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ .global _tx_thread_interrupt_restore
+ .thumb_func
+_tx_thread_interrupt_restore:
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S
new file mode 100644
index 00000000..57c109f1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S
@@ -0,0 +1,331 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+#endif
+#ifdef TX_LOW_POWER
+ .global tx_low_power_enter
+ .global tx_low_power_exit
+#endif
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+
+#ifdef __ARM_PCS_VFP
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .syntax unified
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARM_PCS_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARM_PCS_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+#ifdef __ARM_PCS_VFP
+
+ .global tx_thread_fpu_enable
+ .thumb_func
+tx_thread_fpu_enable:
+ .global tx_thread_fpu_disable
+ .thumb_func
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_stack_build.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..162eba62
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_stack_build.S
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .global _tx_thread_stack_build
+ .thumb_func
+_tx_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S
new file mode 100644
index 00000000..756405f3
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.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 */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ .thumb_func
+ .global _tx_thread_system_return
+_tx_thread_system_return:
+
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context:
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_timer_interrupt.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..a896426d
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_timer_interrupt.S
@@ -0,0 +1,261 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .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_thread_time_slice
+ .global _tx_timer_expiration_process
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+#ifndef TX_NO_TIMER
+ .global _tx_timer_interrupt
+ .thumb_func
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ STMDB sp!, {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/ghs/example_build/sample_threadx.c b/ports_arch/ARMv7-M/threadx/ghs/example_build/sample_threadx.c
new file mode 100644
index 00000000..8c61de06
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/example_build/sample_threadx.c
@@ -0,0 +1,369 @@
+/* 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 "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;
+
+
+/* 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", first_unused_memory, 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;
+ }
+}
+
+
+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_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm
new file mode 100644
index 00000000..7102a92d
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm
@@ -0,0 +1,232 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SYSTEM_CLOCK = 6000000
+ SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-M7/GHS */
+/* 6.1 */
+/* 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 */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+/* VOID _tx_initialize_low_level(VOID)
+{ */
+ .globl _tx_initialize_low_level
+_tx_initialize_low_level:
+
+ /* Disable interrupts. */
+
+ CPSID i ; Disable interrupts
+
+
+ /* Save the system stack pointer. */
+ /* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */
+
+ LDR r1,=_tx_thread_system_stack_ptr ; Pickup address of system stack ptr
+ STR sp, [r1] ; Save system stack
+
+
+ /* Save the first available memory address. */
+ /* _tx_initialize_unused_memory = (VOID_PTR) __ghsbegin_free_mem; */
+
+ LDR r0,=__ghsbegin_free_mem ; Pickup free memory address
+ LDR r2,=_tx_initialize_unused_memory ; Pickup unused memory ptr address
+ STR r0, [r2] ; Save first free memory address
+
+
+ /* Enable the cycle count register. */
+
+ LDR r0, =0xE0001000 ; Build address of DWT register
+ LDR r1, [r0] ; Pickup the current value
+ ORR r1, r1, 1 ; Set the CYCCNTENA bit
+ STR r1, [r0] ; Enable the cycle count register
+
+
+ /* Setup Vector Table Offset Register. */
+
+ MOV r0, 0xE000E000 ; Build address of NVIC registers
+ LDR r1, =__vectors ; Pickup address of vector table
+ STR r1, [r0, 0xD08] ; Set vector table address
+
+
+ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
+
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, 0x14] ; Setup SysTick Reload Value
+ MOV r1, 0x7 ; Build SysTick Control Enable Value
+ STR r1, [r0, 0x10] ; Setup SysTick Control
+
+ /* Configure handler priorities. */
+
+ LDR r1, =0x00000000 ; Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, 0xD18] ; Setup System Handlers 4-7 Priority Registers
+
+ LDR r1, =0xFF000000 ; SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, 0xD1C] ; Setup System Handlers 8-11 Priority Registers
+ ; Note: SVC must be lowest priority, which is 0xFF
+
+ LDR r1, =0x40FF0000 ; SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, 0xD20] ; Setup System Handlers 12-15 Priority Registers
+ ; Note: PnSV must be lowest priority, which is 0xFF
+
+#ifdef __VFP__
+ LDR r0, =0xE000EF34 ; Pickup FPCCR
+ LDR r1, [r0] ;
+ LDR r2, =0x3FFFFFFF ; Build mask to clear ASPEN and LSPEN
+ AND r1, r1, r2 ; Clear the ASPEN and LSPEN bits
+ STR r1, [r0] ; Update FPCCR
+#endif
+
+ /* Return to caller. */
+
+ BX lr ; Return to caller
+
+ .type _tx_initialize_low_level,$function
+ .size _tx_initialize_low_level,.-_tx_initialize_low_level
+/* } */
+
+
+/* Define shells for each of the interrupt vectors. */
+
+ .globl __tx_BadHandler
+__tx_BadHandler:
+ B __tx_BadHandler
+
+ .type __tx_BadHandler,$function
+ .size __tx_BadHandler,.-__tx_BadHandler
+
+
+ .globl __tx_IntHandler
+__tx_IntHandler:
+ PUSH {lr}
+ BL _tx_thread_context_save
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ MOV r0, 0 ; Build interrupt code
+ BL _tx_el_interrupt ; Call interrupt event logging
+#endif
+
+; /* Do interrupt handler work here */
+; /* .... */
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ MOV r0, 0 ; Build interrupt code
+ BL _tx_el_interrupt_end ; Call interrupt event logging
+#endif
+
+ B _tx_thread_context_restore
+
+ .type __tx_IntHandler,$function
+ .size __tx_IntHandler,.-__tx_IntHandler
+
+
+ .globl __tx_SysTickHandler
+__tx_SysTickHandler:
+ PUSH {lr}
+ BL _tx_thread_context_save
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ MOV r0, 15 ; Build interrupt code
+ BL _tx_el_interrupt ; Call interrupt event logging
+#endif
+
+ BL _tx_timer_interrupt
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+ MOV r0, 15 ; Build interrupt code
+ BL _tx_el_interrupt_end ; Call interrupt event logging
+#endif
+
+ B _tx_thread_context_restore
+
+ .type __tx_SysTickHandler,$function
+ .size __tx_SysTickHandler,.-__tx_SysTickHandler
+
+
+ .globl __tx_NMIHandler
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+ .type __tx_NMIHandler,$function
+ .size __tx_NMIHandler,.-__tx_NMIHandler
+
+
+ .globl __tx_DBGHandler
+__tx_DBGHandler:
+ B __tx_DBGHandler
+
+ .type __tx_DBGHandler,$function
+ .size __tx_DBGHandler,.-__tx_DBGHandler
+
+
+ .globl __tx_SVCallHandler
+__tx_SVCallHandler:
+ B __tx_SVCallHandler
+
+ .type __tx_SVCallHandler,$function
+ .size __tx_SVCallHandler,.-__tx_SVCallHandler
+
+
+ /* Reference build options and version ID to ensure they come in. */
+
+BUILD_OPTIONS:
+ .data.w _tx_build_options
+VERSION_ID:
+ .data.w _tx_version_id
diff --git a/ports_arch/ARMv7-M/threadx/ghs/inc/tx_el.h b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_el.h
new file mode 100644
index 00000000..66cc0d7c
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_el.h
@@ -0,0 +1,765 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX/GHS Event Log (EL) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_el.h PORTABLE C/GHS */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX event log functions for the GHS MULTI */
+/* EventAnalyzer. It is assumed that tx_api.h and tx_port.h have */
+/* already been included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_EL_H
+#define TX_EL_H
+
+
+/* Define Event Log specific data definitions. */
+
+#define TX_EL_VERSION_ID 2 /* Event log version ID */
+#define TX_EL_HEADER_SIZE 24 /* Event log header size */
+#define TX_EL_TNIS 16 /* Number of thread names supported */
+ /* If the application needs to */
+ /* track more thread names, just */
+ /* increase this number and re- */
+ /* build the ThreadX library. */
+#define TX_EL_TNI_ENTRY_SIZE 44 /* Thread name entries are 44 bytes */
+#define TX_EL_TNI_NAME_SIZE 34 /* Thread name size in TNI */
+#define TX_EL_NO_MORE_TNI_ROOM 1 /* Error return from thread register*/
+#define TX_EL_NAME_NOT_FOUND 2 /* Error return from un-register */
+#define TX_EL_EVENT_SIZE 32 /* Number of bytes in each event */
+#define TX_EL_VALID_ENTRY 1 /* Valid log entry */
+#define TX_EL_INVALID_ENTRY 0 /* Invalid log entry */
+
+
+/* Define necessary offsets. */
+
+#define TX_EL_TNI_VALID_OFFSET 34
+#define TX_EL_TNI_THREAD_ID_OFFSET 36
+#define TX_EL_TNI_THREAD_PRIORITY_OFF 40
+#define TX_EL_EVENT_TYPE_OFFSET 0
+#define TX_EL_EVENT_SUBTYPE_OFFSET 2
+#define TX_EL_EVENT_TIME_UPPER_OFFSET 4
+#define TX_EL_EVENT_TIME_LOWER_OFFSET 8
+#define TX_EL_EVENT_THREAD_OFFSET 12
+#define TX_EL_EVENT_INFO_1_OFFSET 16
+#define TX_EL_EVENT_INFO_2_OFFSET 20
+#define TX_EL_EVENT_INFO_3_OFFSET 24
+#define TX_EL_EVENT_INFO_4_OFFSET 28
+
+
+/* Undefine constants that might be been defined previously by tx_api.h. */
+
+#undef TX_EL_INITIALIZE
+#undef TX_EL_THREAD_REGISTER
+#undef TX_EL_THREAD_UNREGISTER
+#undef TX_EL_THREAD_STATUS_CHANGE_INSERT
+#undef TX_EL_BYTE_ALLOCATE_INSERT
+#undef TX_EL_BYTE_POOL_CREATE_INSERT
+#undef TX_EL_BYTE_POOL_DELETE_INSERT
+#undef TX_EL_BYTE_RELEASE_INSERT
+#undef TX_EL_BLOCK_ALLOCATE_INSERT
+#undef TX_EL_BLOCK_POOL_CREATE_INSERT
+#undef TX_EL_BLOCK_POOL_DELETE_INSERT
+#undef TX_EL_BLOCK_RELEASE_INSERT
+#undef TX_EL_EVENT_FLAGS_CREATE_INSERT
+#undef TX_EL_EVENT_FLAGS_DELETE_INSERT
+#undef TX_EL_EVENT_FLAGS_GET_INSERT
+#undef TX_EL_EVENT_FLAGS_SET_INSERT
+#undef TX_EL_INTERRUPT_CONTROL_INSERT
+#undef TX_EL_QUEUE_CREATE_INSERT
+#undef TX_EL_QUEUE_DELETE_INSERT
+#undef TX_EL_QUEUE_FLUSH_INSERT
+#undef TX_EL_QUEUE_RECEIVE_INSERT
+#undef TX_EL_QUEUE_SEND_INSERT
+#undef TX_EL_SEMAPHORE_CREATE_INSERT
+#undef TX_EL_SEMAPHORE_DELETE_INSERT
+#undef TX_EL_SEMAPHORE_GET_INSERT
+#undef TX_EL_SEMAPHORE_PUT_INSERT
+#undef TX_EL_THREAD_CREATE_INSERT
+#undef TX_EL_THREAD_DELETE_INSERT
+#undef TX_EL_THREAD_IDENTIFY_INSERT
+#undef TX_EL_THREAD_PREEMPTION_CHANGE_INSERT
+#undef TX_EL_THREAD_PRIORITY_CHANGE_INSERT
+#undef TX_EL_THREAD_RELINQUISH_INSERT
+#undef TX_EL_THREAD_RESUME_INSERT
+#undef TX_EL_THREAD_SLEEP_INSERT
+#undef TX_EL_THREAD_SUSPEND_INSERT
+#undef TX_EL_THREAD_TERMINATE_INSERT
+#undef TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT
+#undef TX_EL_TIME_GET_INSERT
+#undef TX_EL_TIME_SET_INSERT
+#undef TX_EL_TIMER_ACTIVATE_INSERT
+#undef TX_EL_TIMER_CHANGE_INSERT
+#undef TX_EL_TIMER_CREATE_INSERT
+#undef TX_EL_TIMER_DEACTIVATE_INSERT
+#undef TX_EL_TIMER_DELETE_INSERT
+#undef TX_EL_BLOCK_POOL_INFO_GET_INSERT
+#undef TX_EL_BLOCK_POOL_PRIORITIZE_INSERT
+#undef TX_EL_BYTE_POOL_INFO_GET_INSERT
+#undef TX_EL_BYTE_POOL_PRIORITIZE_INSERT
+#undef TX_EL_EVENT_FLAGS_INFO_GET_INSERT
+#undef TX_EL_MUTEX_CREATE_INSERT
+#undef TX_EL_MUTEX_DELETE_INSERT
+#undef TX_EL_MUTEX_GET_INSERT
+#undef TX_EL_MUTEX_INFO_GET_INSERT
+#undef TX_EL_MUTEX_PRIORITIZE_INSERT
+#undef TX_EL_MUTEX_PUT_INSERT
+#undef TX_EL_QUEUE_INFO_GET_INSERT
+#undef TX_EL_QUEUE_FRONT_SEND_INSERT
+#undef TX_EL_QUEUE_PRIORITIZE_INSERT
+#undef TX_EL_SEMAPHORE_INFO_GET_INSERT
+#undef TX_EL_SEMAPHORE_PRIORITIZE_INSERT
+#undef TX_EL_THREAD_INFO_GET_INSERT
+#undef TX_EL_THREAD_WAIT_ABORT_INSERT
+#undef TX_EL_TIMER_INFO_GET_INSERT
+#undef TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT
+#undef TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_QUEUE_SEND_NOTIFY_INSERT
+#undef TX_EL_SEMAPHORE_CEILING_PUT_INSERT
+#undef TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT
+#undef TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT
+#undef TX_EL_THREAD_RESET_INSERT
+#undef TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+#undef TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT
+#undef TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT
+#undef TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT
+
+
+/* Define Event Types. */
+
+#define TX_EL_THREAD_CHANGE 1
+#define TX_EL_INTERRUPT 2
+#define TX_EL_THREADX_CALL 3
+#define TX_EL_USER_EVENT 4
+#define TX_EL_THREAD_STATUS_CHANGE 5
+#define TX_EL_REFRESH 6 /* Not implemented */
+#define TX_EL_TIMER 7 /* Not implemented */
+#define TX_EL_TIMESOURCE_DELTA 8 /* Not implemented */
+
+
+/* Define TX_EL_THREADX_CALL event sub-types. */
+
+#define TX_EL_BYTE_ALLOCATE 0
+#define TX_EL_BYTE_POOL_CREATE 1
+#define TX_EL_BYTE_POOL_DELETE 2
+#define TX_EL_BYTE_RELEASE 3
+#define TX_EL_BLOCK_ALLOCATE 4
+#define TX_EL_BLOCK_POOL_CREATE 5
+#define TX_EL_BLOCK_POOL_DELETE 6
+#define TX_EL_BLOCK_RELEASE 7
+#define TX_EL_EVENT_FLAGS_CREATE 8
+#define TX_EL_EVENT_FLAGS_DELETE 9
+#define TX_EL_EVENT_FLAGS_GET 10
+#define TX_EL_EVENT_FLAGS_SET 11
+#define TX_EL_INTERRUPT_CONTROL 12
+#define TX_EL_QUEUE_CREATE 13
+#define TX_EL_QUEUE_DELETE 14
+#define TX_EL_QUEUE_FLUSH 15
+#define TX_EL_QUEUE_RECEIVE 16
+#define TX_EL_QUEUE_SEND 17
+#define TX_EL_SEMAPHORE_CREATE 18
+#define TX_EL_SEMAPHORE_DELETE 19
+#define TX_EL_SEMAPHORE_GET 20
+#define TX_EL_SEMAPHORE_PUT 21
+#define TX_EL_THREAD_CREATE 22
+#define TX_EL_THREAD_DELETE 23
+#define TX_EL_THREAD_IDENTIFY 24
+#define TX_EL_THREAD_PREEMPTION_CHANGE 25
+#define TX_EL_THREAD_PRIORITY_CHANGE 26
+#define TX_EL_THREAD_RELINQUISH 27
+#define TX_EL_THREAD_RESUME 28
+#define TX_EL_THREAD_SLEEP 29
+#define TX_EL_THREAD_SUSPEND 30
+#define TX_EL_THREAD_TERMINATE 31
+#define TX_EL_THREAD_TIME_SLICE_CHANGE 32
+#define TX_EL_TIME_GET 33
+#define TX_EL_TIME_SET 34
+#define TX_EL_TIMER_ACTIVATE 35
+#define TX_EL_TIMER_CHANGE 36
+#define TX_EL_TIMER_CREATE 37
+#define TX_EL_TIMER_DEACTIVATE 38
+#define TX_EL_TIMER_DELETE 39
+#define TX_EL_BLOCK_POOL_INFO_GET 40
+#define TX_EL_BLOCK_POOL_PRIORITIZE 41
+#define TX_EL_BYTE_POOL_INFO_GET 42
+#define TX_EL_BYTE_POOL_PRIORITIZE 43
+#define TX_EL_EVENT_FLAGS_INFO_GET 44
+#define TX_EL_MUTEX_CREATE 45
+#define TX_EL_MUTEX_DELETE 46
+#define TX_EL_MUTEX_GET 47
+#define TX_EL_MUTEX_INFO_GET 48
+#define TX_EL_MUTEX_PRIORITIZE 49
+#define TX_EL_MUTEX_PUT 50
+#define TX_EL_QUEUE_INFO_GET 51
+#define TX_EL_QUEUE_FRONT_SEND 52
+#define TX_EL_QUEUE_PRIORITIZE 53
+#define TX_EL_SEMAPHORE_INFO_GET 54
+#define TX_EL_SEMAPHORE_PRIORITIZE 55
+#define TX_EL_THREAD_INFO_GET 56
+#define TX_EL_THREAD_WAIT_ABORT 57
+#define TX_EL_TIMER_INFO_GET 58
+#define TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET 59
+#define TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET 60
+#define TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET 61
+#define TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET 62
+#define TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET 63
+#define TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET 64
+#define TX_EL_EVENT_FLAGS_SET_NOTIFY 65
+#define TX_EL_MUTEX_PERFORMANCE_INFO_GET 66
+#define TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET 67
+#define TX_EL_QUEUE_PERFORMANCE_INFO_GET 68
+#define TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET 69
+#define TX_EL_QUEUE_SEND_NOTIFY 70
+#define TX_EL_SEMAPHORE_CEILING_PUT 71
+#define TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET 72
+#define TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET 73
+#define TX_EL_SEMAPHORE_PUT_NOTIFY 74
+#define TX_EL_THREAD_ENTRY_EXIT_NOTIFY 75
+#define TX_EL_THREAD_RESET 76
+#define TX_EL_THREAD_PERFORMANCE_INFO_GET 77
+#define TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET 78
+#define TX_EL_THREAD_STACK_ERROR_NOTIFY 79
+#define TX_EL_TIMER_PERFORMANCE_INFO_GET 80
+#define TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET 81
+
+
+/* Define ThreadX sub-types. */
+
+#define TX_EL_INTERRUPT_SUB_TYPE 1
+#define TX_EL_END_OF_INTERRUPT 3
+
+
+/* Define event logging filters, which may be used by the application program to
+ dynamically enable/disable events in run-time. */
+
+#define TX_EL_FILTER_STATUS_CHANGE 0x0001
+#define TX_EL_FILTER_INTERRUPTS 0x0002
+#define TX_EL_FILTER_THREAD_CALLS 0x0004
+#define TX_EL_FILTER_TIMER_CALLS 0x0008
+#define TX_EL_FILTER_EVENT_FLAG_CALLS 0x0010
+#define TX_EL_FILTER_SEMAPHORE_CALLS 0x0020
+#define TX_EL_FILTER_QUEUE_CALLS 0x0040
+#define TX_EL_FILTER_BLOCK_CALLS 0x0080
+#define TX_EL_FILTER_BYTE_CALLS 0x0100
+#define TX_EL_FILTER_MUTEX_CALLS 0x0200
+#define TX_EL_FILTER_ALL_EVENTS 0xFFFF
+#define TX_EL_ENABLE_ALL_EVENTS 0x0000
+
+
+/* Define filter macros that are inserted in-line with the other macros below. */
+
+#ifdef TX_ENABLE_EVENT_FILTERS
+#define TX_EL_NO_STATUS_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_STATUS_CHANGE)) {
+#define TX_EL_NO_INTERRUPT_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_INTERRUPTS)) {
+#define TX_EL_NO_THREAD_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_THREAD_CALLS)) {
+#define TX_EL_NO_TIMER_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_TIMER_CALLS)) {
+#define TX_EL_NO_EVENT_FLAG_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_EVENT_FLAG_CALLS)) {
+#define TX_EL_NO_SEMAPHORE_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_SEMAPHORE_CALLS)) {
+#define TX_EL_NO_QUEUE_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_QUEUE_CALLS)) {
+#define TX_EL_NO_BLOCK_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_BLOCK_CALLS)) {
+#define TX_EL_NO_BYTE_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_BYTE_CALLS)) {
+#define TX_EL_NO_MUTEX_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_MUTEX_CALLS)) {
+#define TX_EL_END_FILTER }
+#else
+#define TX_EL_NO_STATUS_EVENTS
+#define TX_EL_NO_INTERRUPT_EVENTS
+#define TX_EL_NO_THREAD_EVENTS
+#define TX_EL_NO_TIMER_EVENTS
+#define TX_EL_NO_EVENT_FLAG_EVENTS
+#define TX_EL_NO_SEMAPHORE_EVENTS
+#define TX_EL_NO_QUEUE_EVENTS
+#define TX_EL_NO_BLOCK_EVENTS
+#define TX_EL_NO_BYTE_EVENTS
+#define TX_EL_NO_MUTEX_EVENTS
+#define TX_EL_END_FILTER
+#endif
+
+/* Define externs and constants for non-event log source modules. This is for
+ the in-line macros below. */
+
+#ifndef TX_EL_SOURCE_CODE
+extern UCHAR *_tx_el_tni_start;
+extern UCHAR **_tx_el_current_event;
+extern UCHAR *_tx_el_event_area_start;
+extern UCHAR *_tx_el_event_area_end;
+extern UINT _tx_el_maximum_events;
+extern ULONG _tx_el_total_events;
+extern TX_THREAD *_tx_thread_current_ptr;
+extern UINT _tx_el_event_filter;
+extern ULONG _tx_el_time_base_upper;
+extern ULONG _tx_el_time_base_lower;
+
+
+/* Define macros for event logging functions. */
+
+#define TX_EL_THREAD_CREATE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_THREAD_CREATE, thread_ptr, stack_start, stack_size, priority); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_SET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option); TX_EL_END_FILTER
+#define TX_EL_THREAD_DELETE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_DELETE, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_INFO_GET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_INFO_GET, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_THREAD_TIME_SLICE_CHANGE, thread_ptr, thread_ptr -> tx_thread_new_time_slice, new_time_slice); TX_EL_END_FILTER
+#define TX_EL_THREAD_TERMINATE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_TERMINATE, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_SLEEP_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_SLEEP, timer_ticks); TX_EL_END_FILTER
+#define TX_EL_THREAD_SUSPEND_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_SUSPEND, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_RELINQUISH_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_THREAD_RELINQUISH); TX_EL_END_FILTER
+#define TX_EL_THREAD_RESUME_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_RESUME, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_PRIORITY_CHANGE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_THREAD_PRIORITY_CHANGE, thread_ptr, thread_ptr -> tx_thread_priority, new_priority); TX_EL_END_FILTER
+#define TX_EL_THREAD_PREEMPTION_CHANGE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_THREAD_PREEMPTION_CHANGE, thread_ptr, thread_ptr -> tx_thread_preempt_threshold, new_threshold); TX_EL_END_FILTER
+#define TX_EL_THREAD_WAIT_ABORT_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_WAIT_ABORT, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_THREAD_ENTRY_EXIT_NOTIFY, thread_ptr, thread_entry_exit_notify); TX_EL_END_FILTER
+#define TX_EL_THREAD_RESET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_RESET, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_PERFORMANCE_INFO_GET, thread_ptr); TX_EL_END_FILTER
+#define TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_STACK_ERROR_NOTIFY, stack_error_handler); TX_EL_END_FILTER
+#define TX_EL_TIME_SET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIME_SET, new_time); TX_EL_END_FILTER
+#define TX_EL_TIME_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIME_GET, _tx_timer_system_clock); TX_EL_END_FILTER
+#define TX_EL_TIMER_DELETE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_DELETE, timer_ptr); TX_EL_END_FILTER
+#define TX_EL_TIMER_CREATE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_TIMER_CREATE, timer_ptr, initial_ticks, reschedule_ticks, auto_activate); TX_EL_END_FILTER
+#define TX_EL_TIMER_CHANGE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_TIMER_CHANGE, timer_ptr, initial_ticks, reschedule_ticks); TX_EL_END_FILTER
+#define TX_EL_THREAD_IDENTIFY_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_THREAD_IDENTIFY); TX_EL_END_FILTER
+#define TX_EL_TIMER_DEACTIVATE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_DEACTIVATE, timer_ptr); TX_EL_END_FILTER
+#define TX_EL_TIMER_ACTIVATE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_ACTIVATE, timer_ptr); TX_EL_END_FILTER
+#define TX_EL_TIMER_INFO_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_INFO_GET, timer_ptr); TX_EL_END_FILTER
+#define TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_PERFORMANCE_INFO_GET, timer_ptr); TX_EL_END_FILTER
+#define TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_PUT_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_GET, semaphore_ptr, semaphore_ptr -> tx_semaphore_count); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_DELETE_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_DELETE, semaphore_ptr); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_CREATE_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_CREATE, semaphore_ptr, initial_count); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_INFO_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_INFO_GET, semaphore_ptr); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_PRIORITIZE_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_PRIORITIZE, semaphore_ptr); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_CEILING_PUT_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, ceiling); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET, semaphore_ptr); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_PUT_NOTIFY, semaphore_ptr, semaphore_put_notify); TX_EL_END_FILTER
+#define TX_EL_QUEUE_FRONT_SEND_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_FRONT_SEND, queue_ptr, source_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_SEND_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_SEND, queue_ptr, source_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_RECEIVE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_RECEIVE, queue_ptr, destination_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_FLUSH_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_FLUSH, queue_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_DELETE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_DELETE, queue_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_CREATE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_QUEUE_CREATE, queue_ptr, queue_start, queue_size, message_size); TX_EL_END_FILTER
+#define TX_EL_QUEUE_INFO_GET_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_INFO_GET, queue_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_PRIORITIZE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_PRIORITIZE, queue_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_PERFORMANCE_INFO_GET, queue_ptr); TX_EL_END_FILTER
+#define TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_QUEUE_SEND_NOTIFY_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_SEND_NOTIFY, queue_ptr, queue_send_notify); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_EVENT_FLAGS_GET, group_ptr, requested_flags, get_option); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_DELETE_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_DELETE, group_ptr); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_CREATE_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_CREATE, group_ptr); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_INFO_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_INFO_GET, group_ptr); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET, group_ptr); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_EVENT_FLAGS_SET_NOTIFY, group_ptr, events_set_notify); TX_EL_END_FILTER
+#define TX_EL_BYTE_RELEASE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_BYTE_RELEASE, pool_ptr, memory_ptr); TX_EL_END_FILTER
+#define TX_EL_BYTE_POOL_DELETE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_DELETE, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BYTE_POOL_CREATE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_BYTE_POOL_CREATE, pool_ptr, pool_start, pool_size); TX_EL_END_FILTER
+#define TX_EL_BYTE_POOL_INFO_GET_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_INFO_GET, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BYTE_POOL_PRIORITIZE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_PRIORITIZE, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BYTE_ALLOCATE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_BYTE_ALLOCATE, pool_ptr, memory_ptr, memory_size); TX_EL_END_FILTER
+#define TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_BLOCK_RELEASE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_BLOCK_RELEASE, pool_ptr, block_ptr); TX_EL_END_FILTER
+#define TX_EL_BLOCK_POOL_DELETE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_DELETE, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BLOCK_POOL_CREATE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_BLOCK_POOL_CREATE, pool_ptr, pool_start, pool_size, block_size); TX_EL_END_FILTER
+#define TX_EL_BLOCK_POOL_INFO_GET_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_INFO_GET, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BLOCK_POOL_PRIORITIZE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_PRIORITIZE, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BLOCK_ALLOCATE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_BLOCK_ALLOCATE, pool_ptr, block_ptr); TX_EL_END_FILTER
+#define TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET, pool_ptr); TX_EL_END_FILTER
+#define TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+#define TX_EL_MUTEX_CREATE_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_MUTEX_CREATE, mutex_ptr, inherit); TX_EL_END_FILTER
+#define TX_EL_MUTEX_DELETE_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_DELETE, mutex_ptr); TX_EL_END_FILTER
+#define TX_EL_MUTEX_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_MUTEX_GET, mutex_ptr, mutex_ptr -> tx_mutex_owner, mutex_ptr -> tx_mutex_ownership_count); TX_EL_END_FILTER
+#define TX_EL_MUTEX_INFO_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_INFO_GET, mutex_ptr); TX_EL_END_FILTER
+#define TX_EL_MUTEX_PRIORITIZE_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_PRIORITIZE, mutex_ptr); TX_EL_END_FILTER
+#define TX_EL_MUTEX_PUT_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_MUTEX_PUT, mutex_ptr, mutex_ptr -> tx_mutex_owner, mutex_ptr -> tx_mutex_ownership_count); TX_EL_END_FILTER
+#define TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_PERFORMANCE_INFO_GET, mutex_ptr); TX_EL_END_FILTER
+#define TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
+
+
+#endif
+
+
+/* Define Event Log function prototypes. */
+
+VOID _tx_el_initialize(VOID);
+UINT _tx_el_thread_register(TX_THREAD *thread_ptr);
+UINT _tx_el_thread_unregister(TX_THREAD *thread_ptr);
+VOID _tx_el_user_event_insert(UINT sub_type, ULONG info_1, ULONG info_2,
+ ULONG info_3, ULONG info_4);
+VOID _tx_el_thread_running(TX_THREAD *thread_ptr);
+VOID _tx_el_thread_preempted(TX_THREAD *thread_ptr);
+VOID _tx_el_interrupt(UINT interrupt_number);
+VOID _tx_el_interrupt_end(UINT interrupt_number);
+VOID _tx_el_interrupt_control_call(void);
+VOID _tx_el_event_log_on(void);
+VOID _tx_el_event_log_off(void);
+VOID _tx_el_event_filter_set(UINT filter);
+
+
+/* Define macros that are used inside the ThreadX source code.
+ If event logging is disabled, these macros will be defined
+ as white space. */
+
+#ifdef TX_ENABLE_EVENT_LOGGING
+#ifndef TX_NO_EVENT_INFO
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(a, b, c, d, e) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
+ (ULONG) b;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =\
+ (ULONG) c;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =\
+ (ULONG) d;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =\
+ (ULONG) e;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(a, b, c, d) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
+ (ULONG) b;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =\
+ (ULONG) c;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =\
+ (ULONG) d;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(a, b, c) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
+ (ULONG) b;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =\
+ (ULONG) c;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(a, b) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
+ (ULONG) b;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(a) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ TX_EL_NO_STATUS_EVENTS \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREAD_STATUS_CHANGE; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) b; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) a;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ TX_EL_END_FILTER \
+ }
+#define TX_EL_THREAD_REGISTER(a) \
+ _tx_el_thread_register(a);
+#define TX_EL_THREAD_UNREGISTER(a) \
+ _tx_el_thread_unregister(a);
+#define TX_EL_INITIALIZE _tx_el_initialize();
+#else
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(a, b, c, d, e) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(a, b, c, d) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(a, b, c) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(a, b) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(a) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) _tx_thread_current_ptr;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ }
+#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b) \
+ { \
+ UCHAR *entry_ptr; \
+ ULONG upper_tbu; \
+ TX_EL_NO_STATUS_EVENTS \
+ entry_ptr = *_tx_el_current_event; \
+ *((unsigned short *) entry_ptr) = TX_EL_THREAD_STATUS_CHANGE; \
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) b; \
+ do { \
+ upper_tbu = read_tbu(); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
+ (ULONG) read_tbl();\
+ } while (upper_tbu != read_tbu()); \
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
+ (ULONG) a;\
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
+ if (entry_ptr >= _tx_el_event_area_end) \
+ {\
+ entry_ptr = _tx_el_event_area_start;\
+ }\
+ *_tx_el_current_event = entry_ptr;\
+ TX_EL_END_FILTER \
+ }
+#define TX_EL_THREAD_REGISTER(a) \
+ _tx_el_thread_register(a);
+#define TX_EL_THREAD_UNREGISTER(a) \
+ _tx_el_thread_unregister(a);
+#define TX_EL_INITIALIZE _tx_el_initialize();
+#endif
+#else
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(a, b, c, d, e)
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(a, b, c, d)
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(a, b, c)
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(a, b)
+#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(a)
+#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b)
+#define TX_EL_THREAD_REGISTER(a)
+#define TX_EL_THREAD_UNREGISTER(a)
+#define TX_EL_INITIALIZE
+#endif
+
+#endif
+
diff --git a/ports_arch/ARMv7-M/threadx/ghs/inc/tx_ghs.h b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_ghs.h
new file mode 100644
index 00000000..ca976916
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_ghs.h
@@ -0,0 +1,77 @@
+/*
+ * ThreadX C/C++ Library Support
+ *
+ * Copyright 1983-2019 Green Hills Software LLC.
+ *
+ * This program is the property of Green Hills Software LLC.,
+ * its contents are proprietary information and no part of it
+ * is to be disclosed to anyone except employees of Green Hills
+ * Software LLC., or as agreed in writing signed by the President
+ * of Green Hills Software LLC.
+ */
+
+#ifndef _TX_GHS_H_
+#define _TX_GHS_H_
+
+#include <signal.h>
+#include <stdio.h>
+#include <time.h>
+#include <setjmp.h>
+
+#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
+extern void *__ghs_GetThreadLocalStorageItem(int specifier);
+
+/* Thread-local storage routines for Green Hills releases 5.x and beyond.
+ The following specifiers are used when calling
+ __ghs_GetThreadLocalStorageItem.
+
+ If __ghs_GetThreadLocalStorageItem is customized to
+ return a per-thread errno value, define the preprocessor symbol
+ USE_THREAD_LOCAL_ERRNO in ind_errn.c.
+ */
+
+enum __ghs_ThreadLocalStorage_specifier {
+ __ghs_TLS_asctime_buff,
+ __ghs_TLS_tmpnam_space,
+ __ghs_TLS_strtok_saved_pos,
+ __ghs_TLS_Errno,
+ __ghs_TLS_gmtime_temp,
+ __ghs_TLS___eh_globals,
+ __ghs_TLS_SignalHandlers
+};
+#else
+/* Thread-local storage routines for Green Hills releases 4.x and 3.x . */
+typedef void (*SignalHandler)(int);
+
+typedef struct
+{
+ int Errno; /* errno. */
+ SignalHandler SignalHandlers[_SIGMAX]; /* signal() buffer. */
+ char tmpnam_space[L_tmpnam]; /* tmpnam(NULL) buffer. */
+ char asctime_buff[30]; /* . */
+ char *strtok_saved_pos; /* strtok() position. */
+ struct tm gmtime_temp; /* gmtime() and localtime() buffer. */
+ void *__eh_globals; /* Pointer for C++ exception handling. */
+} ThreadLocalStorage;
+
+ThreadLocalStorage *GetThreadLocalStorage(void);
+#endif
+
+
+void __ghsLock(void);
+void __ghsUnlock(void);
+
+int __ghs_SaveSignalContext(jmp_buf);
+void __ghs_RestoreSignalContext(jmp_buf);
+
+/* prototypes for FILE lock routines. */
+void __ghs_flock_file(void *);
+void __ghs_funlock_file(void *);
+int __ghs_ftrylock_file(void *);
+void __ghs_flock_create(void **);
+void __ghs_flock_destroy(void *);
+
+/* prototype for GHS/ThreadX error shell checking. */
+void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hexVal);
+
+#endif /* _TX_GHS_H_ */
diff --git a/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h
new file mode 100644
index 00000000..245f5f26
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h
@@ -0,0 +1,406 @@
+/**************************************************************************/
+/* */
+/* 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 Cortex-Mx */
+/* 6.1.7 */
+/* */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
+/* the ARMv7-M architecture and compilers into one common file. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+
+#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 compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __ICCARM__
+#include <intrinsics.h> /* IAR Intrinsics */
+#define __asm__ __asm /* Define to make all inline asm look similar */
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+#endif /* __ICCARM__ */
+
+#ifdef __ghs__
+#include <arm_ghs.h>
+#include "tx_ghs.h"
+#endif /* __ghs__ */
+
+
+/* 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 unsigned long long ULONG64;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#define ULONG64_DEFINED
+
+/* 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 200 /* 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
+
+
+/* Define various constants for the ThreadX Cortex-M port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* 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_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
+#endif
+#else
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#endif
+
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+#ifdef __ghs__
+/* Define constants for Green Hills EventAnalyzer. */
+
+/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
+ represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
+
+#define TX_EL_TICKS_PER_SECOND 1000000
+
+/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
+ simulate the time-stamp source with a counter. */
+
+#define read_tbu() _tx_el_time_base_upper
+#define read_tbl() ++_tx_el_time_base_lower
+#endif /* __ghs__ */
+
+/* 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. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* 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. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#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 VOID * tx_thread_eh_globals; \
+ int Errno; /* errno. */ \
+ char * strtok_saved_pos; /* strtok() position. */
+#ifndef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+#define TX_THREAD_EXTENSION_3
+#else
+#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
+ unsigned long long tx_thread_execution_time_last_start;
+#endif
+
+
+/* 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 (__GHS_VERSION_NUMBER >= 500)
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) \
+ { \
+ extern void __tx_cpp_exception_init(TX_THREAD *thread_ptr); \
+ __tx_cpp_exception_init(thread_ptr); \
+ }
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) \
+ { \
+ #pragma weak __cpp_exception_init \
+ extern void __cpp_exception_init(void **); \
+ static void (*const cpp_init_funcp)(void **) = __cpp_exception_init; \
+ if (cpp_init_funcp) \
+ __cpp_exception_init(&(thread_ptr -> tx_thread_eh_globals)); \
+ }
+#endif
+
+#if (__GHS_VERSION_NUMBER >= 500)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) \
+ { \
+ extern void __tx_cpp_exception_cleanup(TX_THREAD *thread_ptr); \
+ __tx_cpp_exception_cleanup(thread_ptr); \
+ }
+#else
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) \
+ { \
+ #pragma weak __cpp_exception_cleanup \
+ extern void __cpp_exception_cleanup(void **); \
+ static void (*const cpp_cleanup_funcp)(void **) = \
+ __cpp_exception_cleanup; \
+ if (cpp_cleanup_funcp) \
+ __cpp_exception_cleanup(&(thread_ptr -> tx_thread_eh_globals)); \
+ }
+#endif
+
+#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 the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __MRS(__IPSR))
+#endif
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
+ for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
+ zero after initialization for Cortex-M ports. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+
+
+#ifndef TX_DISABLE_INLINE
+
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \
+ b = __CLZ32(m); \
+ b = 31 - b;
+
+#endif
+
+
+
+
+#ifdef TX_DISABLE_INLINE
+
+UINT _tx_thread_interrupt_disable(VOID);
+VOID _tx_thread_interrupt_restore(UINT previous_posture);
+
+#define TX_INTERRUPT_SAVE_AREA register int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA register int interrupt_save;
+
+/* Define ThreadX interrupt lockout and restore macros using
+ asm macros. */
+
+asm int disable_ints(void)
+{
+%
+ MRS r0,PRIMASK
+ MOV r1,1
+ MSR PRIMASK,r1
+%error
+}
+
+asm void restore_ints(int a)
+{
+%reg a
+ MSR PRIMASK,a
+%mem a
+ LDR r0,a
+ MSR PRIMASK,r0
+%error
+}
+
+#define TX_DISABLE interrupt_save = disable_ints();
+
+#define TX_RESTORE restore_ints(interrupt_save);
+
+#endif
+
+
+/* Define FPU extension for the Cortex-M. Each is assumed to be called in the context of the executing
+ thread. These are no longer needed, but are preserved for backward compatibility only. */
+
+void tx_thread_fpu_enable(void);
+void tx_thread_fpu_disable(void);
+
+
+/* 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 ARMv7-M Version 6.2.1 *";
+#else
+#ifdef TX_MISRA_ENABLE
+extern CHAR _tx_version_id[100];
+#else
+extern CHAR _tx_version_id[];
+#endif
+#endif
+
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/ghs/readme_threadx.txt b/ports_arch/ARMv7-M/threadx/ghs/readme_threadx.txt
new file mode 100644
index 00000000..2f0cc0ea
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/readme_threadx.txt
@@ -0,0 +1,233 @@
+ Microsoft's Azure RTOS ThreadX for Cortex-M7
+
+ Using the Green Hills Software Tools
+
+1. Open the ThreadX Project Workspace
+
+In order to build the ThreadX library and the ThreadX demonstration first load
+the Azure RTOS Workspace azure_rtos_workspace.gpj, which is located inside the
+"example_build" directory.
+
+
+2. Building the ThreadX run-time Library
+
+Building the ThreadX library is easy; simply select the MULTI project file
+tx.gpj and then select the build button. You should now observe the
+compilation and assembly of the ThreadX library. This project build produces
+the ThreadX library file tx.a.
+
+
+3. Demonstration System
+
+The ThreadX demonstration is designed to execute under the MULTI environment
+on the Green Hills Cortex-M7 simulator. The instructions that follow describe
+how to get the ThreadX evaluation running under the MULTI Cortex-M7 simulation
+environment.
+
+Building the demonstration is easy; simply select the MULTI project file
+sample_threadx.gpj. At this point, select the "Project Build" button and observe
+the compilation, assembly, and linkage of the ThreadX demonstration application.
+
+After the demonstration is built, invoke the MULTI ARM simulator by selecting
+the simulator connection from within the sample_threadx.con connection file.
+Once connected to the simulator, select the "Debug" button. You should now
+observe the main function of sample_threadx.c.
+
+You are now ready to execute the ThreadX demonstration system. Select
+breakpoints and data watches to observe the execution of the sample_threadx.c
+application.
+
+
+4. EventAnalyzer Demonstration
+
+To build a demonstration system that also logs events for the MULTI EventAnalyzer,
+perform the same steps as the regular demo, except build the ThreadX library with
+txe.gpj file and use the sample_threadx_el.gpj build file to build the demonstration.
+The resulting image will log all system events, which can then be displayed by the
+MULTI EventAnalyzer.
+
+
+5. System Initialization
+
+The system entry point using the Green Hills tools is at the label _start.
+This is defined within the crt0.arm file supplied by Green Hills. In addition,
+this is where all static and global preset C variable initialization
+processing is called from.
+
+After the Green Hills startup function returns, ThreadX initialization is
+called. The main initialization function is _tx_initialize_low_level and
+is located in the file tx_initialize_low_level.arm. This function is responsible
+for setting up various system data structures, interrupt vectors, and the
+periodic timer interrupt source of ThreadX.
+
+In addition, _tx_initialize_low_level determines where the first available
+RAM memory address is located. This address is supplied to tx_application_define.
+
+By default, the first available RAM memory address is assumed to start at the
+beginning of the ThreadX section .free_mem. If changes are made to the
+sample_threadx.ld file, the .free_mem section should remain the last allocated
+section in the main RAM area. The starting address of this section is passed
+to tx_application_define.
+
+
+6. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-M7 version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 r4
+ 0x04 r5
+ 0x08 r6
+ 0x0C r7
+ 0x10 r8
+ 0x14 r9
+ 0x18 r10
+ 0x1C r11
+ 0x20 r0 (Hardware stack starts here!!)
+ 0x24 r1
+ 0x28 r2
+ 0x2C r3
+ 0x30 r12
+ 0x34 lr
+ 0x38 pc
+ 0x3C xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 s0
+ 0x04 s1
+ 0x08 s2
+ 0x0C s3
+ 0x10 s4
+ 0x14 s5
+ 0x18 s6
+ 0x1C s7
+ 0x20 s8
+ 0x24 s9
+ 0x28 s10
+ 0x2C s11
+ 0x30 s12
+ 0x34 s13
+ 0x38 s14
+ 0x3C s15
+ 0x40 s16
+ 0x44 s17
+ 0x48 s18
+ 0x4C s19
+ 0x50 s20
+ 0x54 s21
+ 0x58 s22
+ 0x5C s23
+ 0x60 s24
+ 0x64 s25
+ 0x68 s26
+ 0x6C s27
+ 0x70 s28
+ 0x74 s29
+ 0x78 s30
+ 0x7C s31
+ 0x80 fpscr
+ 0x84 r4
+ 0x88 r5
+ 0x8C r6
+ 0x90 r7
+ 0x94 r8
+ 0x98 r9
+ 0x9C r10 (sl)
+ 0xA0 r11
+ 0xA4 r0 (Hardware stack starts here!!)
+ 0xA8 r1
+ 0xAC r2
+ 0xB0 r3
+ 0xB4 r12
+ 0xB8 lr
+ 0xBC pc
+ 0xC0 xPSR
+
+
+7. 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 tx.gpj 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.
+
+
+8. Interrupt Handling
+
+ThreadX provides complete and high-performance interrupt handling for Cortex-M7
+targets. There are a certain set of requirements that are defined in the
+following sub-sections:
+
+
+8.1 Vector Area
+
+The Cortex-M7 vectors start at the label __tx_vectors. The application may modify
+the vector area according to its needs.
+
+
+8.2 Managed Interrupts
+
+A ThreadX managed interrupt is defined below. By following these conventions, the
+application ISR is then allowed access to various ThreadX services from the ISR.
+Here is the standard template for managed ISRs in ThreadX:
+
+
+ .globl __tx_IntHandler
+__tx_IntHandler:
+ PUSH {lr}
+ BL _tx_thread_context_save
+
+ /* Do interrupt handler work here */
+
+ B _tx_thread_context_restore
+
+
+9. FPU Support
+
+By default, FPU support is disabled for each thread. If saving the context of the FPU registers
+is needed, the ThreadX library should be re-built with TX_ENABLE_FPU_SUPPORT defined. In addition,
+the following API call must be made from the context of the application thread - before
+the FPU usage:
+
+void tx_thread_fpu_enable(void);
+
+After this API is called in the application, FPU registers will be saved/restored for this thread if it
+is preempted via an interrupt. All other suspension of the this thread will not require the FPU registers
+to be saved/restored.
+
+To disable FPU register context saving, simply call the following API:
+
+void tx_thread_fpu_disable(void);
+
+
+
+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:
+
+05/19/2020 Initial ThreadX version of Cortex-M7/Green Hills port.
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_el.c b/ports_arch/ARMv7-M/threadx/ghs/src/tx_el.c
new file mode 100644
index 00000000..d8f056d7
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_el.c
@@ -0,0 +1,1165 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX/GHS Event Log (EL) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+#define TX_EL_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_el.h"
+#include "string.h"
+
+
+/* Define global variables used to manage the event pool. */
+
+UCHAR *_tx_el_tni_start;
+UCHAR **_tx_el_current_event;
+UCHAR *_tx_el_event_area_start;
+UCHAR *_tx_el_event_area_end;
+UINT _tx_el_maximum_events;
+ULONG _tx_el_total_events;
+UINT _tx_el_event_filter;
+ULONG _tx_el_time_base_upper;
+ULONG _tx_el_time_base_lower;
+
+extern char __ghsbegin_eventlog[];
+extern char __ghsend_eventlog[];
+
+extern TX_THREAD *_tx_thread_current_ptr;
+UINT _tx_thread_interrupt_control(UINT new_posture);
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_initialize PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates the Event Log (in the format dictated by the */
+/* GHS Event Analyzer) and sets up various information for subsequent */
+/* operation. The start and end of the Event Log is determined by the */
+/* .eventlog section in the linker control file. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_initialize(VOID)
+{
+
+UCHAR *work_ptr;
+UCHAR *read_ptr;
+ULONG event_log_size;
+UCHAR *end_ptr;
+UINT i;
+
+
+ /* Clear total event counter. */
+ _tx_el_total_events = 0;
+
+ /* Clear event filter. */
+ _tx_el_event_filter = 0;
+
+ /* First, pickup the starting and ending address of the Event Log memory. */
+ work_ptr = (unsigned char *) __ghsbegin_eventlog;
+ end_ptr = (unsigned char *) __ghsend_eventlog;
+
+ /* Calculate the event log size. */
+ event_log_size = end_ptr - work_ptr;
+
+ /* Subtract off the number of bytes in the header and the TNI area. */
+ event_log_size = event_log_size - (TX_EL_HEADER_SIZE +
+ (TX_EL_TNI_ENTRY_SIZE * TX_EL_TNIS));
+
+ /* Make sure the event log is evenly divisible by the event size. */
+ event_log_size = (event_log_size/TX_EL_EVENT_SIZE) * TX_EL_EVENT_SIZE;
+
+ /* Build the Event Log header. */
+
+ /* Setup the Event Log Version ID. */
+ *((unsigned short *) work_ptr) = (unsigned short) TX_EL_VERSION_ID;
+ work_ptr = work_ptr + sizeof(unsigned short);
+
+ /* Setup the TNIS (number of thread names) field. */
+ *((unsigned short *) work_ptr) = (unsigned short) TX_EL_TNIS;
+ work_ptr = work_ptr + sizeof(unsigned short);
+
+ /* Setup the EVPS (event pool size) field. */
+ *((ULONG *) work_ptr) = event_log_size;
+ work_ptr = work_ptr + sizeof(ULONG);
+
+ /* Remember the maximum number of events. */
+ _tx_el_maximum_events = event_log_size/TX_EL_EVENT_SIZE;
+
+ /* Setup max_events field. */
+ *((ULONG *) work_ptr) = _tx_el_maximum_events;
+ work_ptr = work_ptr + sizeof(ULONG);
+
+ /* Setup the evploc (location of event pool). */
+ *((ULONG *) work_ptr) = (ULONG) (((ULONG) __ghsbegin_eventlog) + TX_EL_HEADER_SIZE +
+ (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
+ work_ptr = work_ptr + sizeof(ULONG);
+
+ /* Save the current event pointer. */
+ _tx_el_current_event = (UCHAR **) work_ptr;
+
+ /* Setup event_ptr (pointer to oldest event) field to the start
+ of the event pool. */
+ *_tx_el_current_event = (UCHAR *) (((ULONG) __ghsbegin_eventlog) + TX_EL_HEADER_SIZE +
+ (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
+ work_ptr = work_ptr + sizeof(ULONG);
+
+ /* Setup tbfreq (the number of ticks in a second) field. */
+ *((ULONG *) work_ptr) = TX_EL_TICKS_PER_SECOND;
+ work_ptr = work_ptr + sizeof(ULONG);
+
+ /* At this point we are pointing at the Thread Name Information (TNI) array. */
+
+ /* Remember the start of this for future updates. */
+ _tx_el_tni_start = work_ptr;
+
+ /* Clear the entire TNI array, this is the initial setting. */
+ end_ptr = work_ptr + (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE);
+ memset((void *)work_ptr, 0, (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
+ work_ptr = end_ptr;
+
+ /* At this point, we are pointing at the actual Event Entry area. */
+
+ /* Remember the start of the actual event log area. */
+ _tx_el_event_area_start = work_ptr;
+
+ /* Clear the entire Event area. */
+ end_ptr = work_ptr + event_log_size;
+ memset((void *)work_ptr, 0, event_log_size);
+ work_ptr = end_ptr;
+
+ /* Save the end pointer for later use. */
+ _tx_el_event_area_end = work_ptr;
+
+ /* Setup an entry to resolve all activities from initialization and from
+ an idle system. */
+ work_ptr = _tx_el_tni_start;
+ read_ptr = (UCHAR *) "Initialization/System Idle";
+ i = 0;
+ while ((i < TX_EL_TNI_NAME_SIZE) && (*read_ptr))
+ {
+
+ /* Copy a character of thread's name into TNI area of log. */
+ *work_ptr++ = *read_ptr++;
+
+ /* Increment the character count. */
+ i++;
+ }
+
+ /* Determine if a NULL needs to be inserted. */
+ if (i < TX_EL_TNI_NAME_SIZE)
+ {
+
+ /* Yes, insert a NULL into the event log string. */
+ *work_ptr = (unsigned char) 0;
+ }
+
+ /* Setup the thread ID to NULL. */
+ *((ULONG *) (_tx_el_tni_start + TX_EL_TNI_THREAD_ID_OFFSET)) = (ULONG) TX_NULL;
+
+ /* Set the valid field to indicate the entry is complete. */
+ *((UCHAR *) (_tx_el_tni_start + TX_EL_TNI_VALID_OFFSET)) = (ULONG) TX_EL_VALID_ENTRY;
+
+ /* Clear the time base global variables. */
+ _tx_el_time_base_upper = 0;
+ _tx_el_time_base_lower = 0;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_thread_register PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers a thread in the event log for future */
+/* display purposes. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Thread was placed in TNI area */
+/* TX_ERROR No more room in the TNI area */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create ThreadX thread create function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _tx_el_thread_register(TX_THREAD *thread_ptr)
+{
+
+UCHAR *entry_ptr;
+UCHAR *work_ptr;
+UCHAR *read_ptr;
+UINT i;
+
+
+ /* First of all, search for a free slot in the TNI area. */
+ entry_ptr = _tx_el_tni_start;
+ i = 0;
+ while (i < TX_EL_TNIS)
+ {
+
+ /* Determine if this entry is available. */
+ if (*(entry_ptr + TX_EL_TNI_VALID_OFFSET) == TX_EL_INVALID_ENTRY)
+ break;
+
+ /* Otherwise, increment the associated pointers and indices. */
+ i++;
+ entry_ptr = entry_ptr + TX_EL_TNI_ENTRY_SIZE;
+ }
+
+ /* Check to see if there were no more valid entries. */
+ if (i >= TX_EL_TNIS)
+ return(TX_EL_NO_MORE_TNI_ROOM);
+
+ /* Otherwise, we have room in the TNI and a valid record. */
+
+ /* Setup the thread's name. */
+ work_ptr = entry_ptr;
+ read_ptr = (UCHAR *) thread_ptr -> tx_thread_name;
+ i = 0;
+ while ((i < TX_EL_TNI_NAME_SIZE) && (*read_ptr))
+ {
+
+ /* Copy a character of thread's name into TNI area of log. */
+ *work_ptr++ = *read_ptr++;
+
+ /* Increment the character count. */
+ i++;
+ }
+
+ /* Determine if a NULL needs to be inserted. */
+ if (i < TX_EL_TNI_NAME_SIZE)
+ {
+
+ /* Yes, insert a NULL into the event log string. */
+ *work_ptr = (unsigned char) 0;
+ }
+
+ /* Setup the thread ID. */
+ *((ULONG *) (entry_ptr + TX_EL_TNI_THREAD_ID_OFFSET)) = (ULONG) thread_ptr;
+
+ /* Setup the thread priority. */
+ *((ULONG *) (entry_ptr + TX_EL_TNI_THREAD_PRIORITY_OFF)) = (ULONG) thread_ptr -> tx_thread_priority;
+
+ /* Set the valid field to indicate the entry is complete. */
+ *((UCHAR *) (entry_ptr + TX_EL_TNI_VALID_OFFSET)) = (ULONG) TX_EL_VALID_ENTRY;
+
+ /* Thread name has been registered. */
+ return(TX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_thread_unregister PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function unregisters a thread in the event log for future */
+/* display purposes. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control block */
+/* */
+/* OUTPUT */
+/* */
+/* TX_SUCCESS Thread was placed in TNI area */
+/* TX_ERROR No more room in the TNI area */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create ThreadX thread create function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _tx_el_thread_unregister(TX_THREAD *thread_ptr)
+{
+
+UCHAR *entry_ptr;
+UCHAR *work_ptr;
+UCHAR *read_ptr;
+UINT found;
+UINT i, j;
+
+
+ /* First of all, search for a match in the TNI area. */
+ entry_ptr = _tx_el_tni_start;
+ i = 0;
+ while (i < TX_EL_TNIS)
+ {
+
+ /* Determine if this entry is a match. */
+ work_ptr = entry_ptr;
+ read_ptr = (UCHAR *) thread_ptr -> tx_thread_name;
+ found = TX_TRUE;
+ j = 0;
+ do
+ {
+
+ /* Determine if this character is the same. */
+ if (*work_ptr != *read_ptr)
+ {
+
+ /* Set found to false and fall out of the loop. */
+ found = TX_FALSE;
+ break;
+ }
+ else if (*work_ptr == 0)
+ {
+
+ /* Null terminated, just break the loop. */
+ break;
+ }
+ else
+ {
+
+ /* Copy a character of thread's name into TNI area of log. */
+ *work_ptr++ = *read_ptr++;
+ }
+
+ /* Increment the character count. */
+ j++;
+
+ } while(j < TX_EL_TNIS);
+
+
+ /* Was a match found? */
+ if (found)
+ {
+
+ /* Yes, mark the entry as available now. */
+ *(entry_ptr + TX_EL_TNI_VALID_OFFSET) = TX_EL_INVALID_ENTRY;
+
+ /* Get out of the loop! */
+ break;
+ }
+
+ /* Otherwise, increment the associated pointers and indices. */
+ i++;
+ entry_ptr = entry_ptr + TX_EL_TNI_ENTRY_SIZE;
+ }
+
+ /* Determine status to return. */
+ if (found)
+ return(TX_SUCCESS);
+ else
+ return(TX_EL_NAME_NOT_FOUND);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_user_event_insert PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function inserts a user event into the event log. */
+/* If the event log is full, the oldest event is overwritten. */
+/* */
+/* INPUT */
+/* */
+/* sub_type Event subtype for kernel call */
+/* info_1 First information field */
+/* info_2 Second information field */
+/* info_3 Third information field */
+/* info_4 Fourth information field */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX services */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_user_event_insert(UINT sub_type, ULONG info_1, ULONG info_2,
+ ULONG info_3, ULONG info_4)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT upper_tb;
+UCHAR *entry_ptr;
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Increment total event counter. */
+ _tx_el_total_events++;
+
+ /* Setup working entry pointer first. */
+ entry_ptr = *_tx_el_current_event;
+
+ /* Store the event type. */
+ *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_USER_EVENT;
+
+ /* Store the event subtype. */
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
+ (unsigned short) sub_type;
+
+ /* Get time stamp. */
+ do
+ {
+
+ /* Pickup the upper tb. */
+ upper_tb = (ULONG) read_tbu();
+
+ /* Store the upper time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
+ (ULONG) upper_tb;
+
+ /* Store the lower time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
+ (ULONG) read_tbl();
+ } while (upper_tb != (ULONG) read_tbu());
+
+ /* Store the current thread. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
+ (ULONG) _tx_thread_current_ptr;
+
+ /* Store the first info field. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
+ (ULONG) info_1;
+
+ /* Store the second info field. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =
+ (ULONG) info_2;
+
+ /* Store the third info field. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =
+ (ULONG) info_3;
+
+ /* Store the fourth info field. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =
+ (ULONG) info_4;
+
+ /* Now move the current event log pointer. */
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
+
+ /* Check for a wraparound condition. */
+ if (entry_ptr >= _tx_el_event_area_end)
+ {
+
+ /* Yes, we have wrapped around to the end of the event area.
+ Start back at the top! */
+ entry_ptr = _tx_el_event_area_start;
+ }
+
+ /* Write the entry pointer back into the header. */
+ *_tx_el_current_event = entry_ptr;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_thread_running PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function inserts a thread change event into the event */
+/* log, which indicates that a context switch is taking place. */
+/* If the event log is full, the oldest event is overwritten. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread being */
+/* scheduled */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_schedule ThreadX scheduler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_thread_running(TX_THREAD *thread_ptr)
+{
+
+UINT upper_tb;
+UCHAR *entry_ptr;
+
+ TX_EL_NO_STATUS_EVENTS
+
+ /* Increment total event counter. */
+ _tx_el_total_events++;
+
+ /* Setup working entry pointer first. */
+ entry_ptr = *_tx_el_current_event;
+
+ /* Store the event type. */
+ *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_THREAD_CHANGE;
+
+ /* Store the event subtype. */
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
+ (unsigned short) 0;
+
+ /* Get time stamp. */
+ do
+ {
+
+ /* Pickup the upper tb. */
+ upper_tb = (ULONG) read_tbu();
+
+ /* Store the upper time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
+ (ULONG) upper_tb;
+
+ /* Store the lower time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
+ (ULONG) read_tbl();
+ } while (upper_tb != (ULONG) read_tbu());
+
+ /* Store the current thread. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
+ (ULONG) thread_ptr;
+
+ /* Now move the current event log pointer. */
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
+
+ /* Check for a wraparound condition. */
+ if (entry_ptr >= _tx_el_event_area_end)
+ {
+
+ /* Yes, we have wrapped around to the end of the event area.
+ Start back at the top! */
+ entry_ptr = _tx_el_event_area_start;
+ }
+
+ /* Write the entry pointer back into the header. */
+ *_tx_el_current_event = entry_ptr;
+
+ TX_EL_END_FILTER
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_thread_preempted PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function inserts a thread preempted event into the event */
+/* log, which indicates that an interrupt occurred that made a higher */
+/* priority thread ready for execution. In this case, the previously */
+/* executing thread has an event entered to indicate it is no longer */
+/* running. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread being */
+/* scheduled */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_context_restore ThreadX context restore */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_thread_preempted(TX_THREAD *thread_ptr)
+{
+
+UINT upper_tb;
+UCHAR *entry_ptr;
+
+
+ TX_EL_NO_STATUS_EVENTS
+
+ /* Increment total event counter. */
+ _tx_el_total_events++;
+
+ /* Setup working entry pointer first. */
+ entry_ptr = *_tx_el_current_event;
+
+ /* Store the event type. */
+ *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_THREAD_STATUS_CHANGE;
+
+ /* Store the event subtype. */
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
+ (unsigned short) TX_READY;
+
+ /* Get time stamp. */
+ do
+ {
+
+ /* Pickup the upper tb. */
+ upper_tb = (ULONG) read_tbu();
+
+ /* Store the upper time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
+ (ULONG) upper_tb;
+
+ /* Store the lower time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
+ (ULONG) read_tbl();
+ } while (upper_tb != (ULONG) read_tbu());
+
+ /* Store the current thread. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
+ (ULONG) _tx_thread_current_ptr;
+
+ /* Now move the current event log pointer. */
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
+
+ /* Check for a wraparound condition. */
+ if (entry_ptr >= _tx_el_event_area_end)
+ {
+
+ /* Yes, we have wrapped around to the end of the event area.
+ Start back at the top! */
+ entry_ptr = _tx_el_event_area_start;
+ }
+
+ /* Write the entry pointer back into the header. */
+ *_tx_el_current_event = entry_ptr;
+
+ TX_EL_END_FILTER
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_interrupt PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function inserts an interrupt event into the log, which */
+/* indicates the start of interrupt processing for the specific */
+/* */
+/* INPUT */
+/* */
+/* interrupt_number Interrupt number supplied by */
+/* ISR */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ISR processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_interrupt(UINT interrupt_number)
+{
+
+UINT upper_tb;
+UCHAR *entry_ptr;
+
+
+ TX_EL_NO_INTERRUPT_EVENTS
+
+ /* Increment total event counter. */
+ _tx_el_total_events++;
+
+ /* Setup working entry pointer first. */
+ entry_ptr = *_tx_el_current_event;
+
+ /* Store the event type. */
+ *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_INTERRUPT;
+
+ /* Store the event subtype. */
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
+ (unsigned short) TX_EL_INTERRUPT_SUB_TYPE;
+
+ /* Get time stamp. */
+ do
+ {
+
+ /* Pickup the upper tb. */
+ upper_tb = (ULONG) read_tbu();
+
+ /* Store the upper time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
+ (ULONG) upper_tb;
+
+ /* Store the lower time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
+ (ULONG) read_tbl();
+ } while (upper_tb != (ULONG) read_tbu());
+
+ /* Store the current thread. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
+ (ULONG) _tx_thread_current_ptr;
+
+ /* Store the first info word. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
+ (ULONG) interrupt_number;
+
+ /* Now move the current event log pointer. */
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
+
+ /* Check for a wraparound condition. */
+ if (entry_ptr >= _tx_el_event_area_end)
+ {
+
+ /* Yes, we have wrapped around to the end of the event area.
+ Start back at the top! */
+ entry_ptr = _tx_el_event_area_start;
+ }
+
+ /* Write the entry pointer back into the header. */
+ *_tx_el_current_event = entry_ptr;
+
+ TX_EL_END_FILTER
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_interrupt_end PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function inserts an interrupt end event into the log, which */
+/* indicates the end of interrupt processing for the specific */
+/* */
+/* INPUT */
+/* */
+/* interrupt_number Interrupt number supplied by */
+/* ISR */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ISR processing */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_interrupt_end(UINT interrupt_number)
+{
+
+UINT upper_tb;
+UCHAR *entry_ptr;
+
+
+ TX_EL_NO_INTERRUPT_EVENTS
+
+ /* Increment total event counter. */
+ _tx_el_total_events++;
+
+ /* Setup working entry pointer first. */
+ entry_ptr = *_tx_el_current_event;
+
+ /* Store the event type. */
+ *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_INTERRUPT;
+
+ /* Store the event subtype. */
+ *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
+ (unsigned short) TX_EL_END_OF_INTERRUPT;
+
+ /* Get time stamp. */
+ do
+ {
+
+ /* Pickup the upper tb. */
+ upper_tb = (ULONG) read_tbu();
+
+ /* Store the upper time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
+ (ULONG) upper_tb;
+
+ /* Store the lower time stamp. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
+ (ULONG) read_tbl();
+ } while (upper_tb != (ULONG) read_tbu());
+
+ /* Store the current thread. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
+ (ULONG) _tx_thread_current_ptr;
+
+ /* Store the first info word. */
+ *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
+ (ULONG) interrupt_number;
+
+ /* Now move the current event log pointer. */
+ entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
+
+ /* Check for a wraparound condition. */
+ if (entry_ptr >= _tx_el_event_area_end)
+ {
+
+ /* Yes, we have wrapped around to the end of the event area.
+ Start back at the top! */
+ entry_ptr = _tx_el_event_area_start;
+ }
+
+ /* Write the entry pointer back into the header. */
+ *_tx_el_current_event = entry_ptr;
+
+ TX_EL_END_FILTER
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_interrupt_control PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function remaps the tx_interrupt_control service call so that */
+/* it can be tracked in the event log. */
+/* */
+/* INPUT */
+/* */
+/* new_posture New interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt posture */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_interrupt_control Interrupt control service */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX services */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _tx_el_interrupt_control(UINT new_posture)
+{
+
+TX_INTERRUPT_SAVE_AREA
+UINT old_posture;
+
+
+ TX_EL_NO_INTERRUPT_EVENTS
+
+ TX_DISABLE
+ TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_INTERRUPT_CONTROL, _tx_thread_current_ptr, new_posture)
+ TX_RESTORE
+
+ TX_EL_END_FILTER
+
+ old_posture = _tx_thread_interrupt_control(new_posture);
+ return(old_posture);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_event_log_on PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function disables all event filters. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_event_log_on(void)
+{
+
+ /* Disable all event filters. */
+ _tx_el_event_filter = TX_EL_ENABLE_ALL_EVENTS;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_event_log_off PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets all event filters, thereby turning event */
+/* logging off. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_event_log_off(void)
+{
+
+ /* Set all event filters. */
+ _tx_el_event_filter = TX_EL_FILTER_ALL_EVENTS;
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_el_event_log_set PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the events filters specified by the user. */
+/* */
+/* INPUT */
+/* */
+/* filter Events to filter */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+VOID _tx_el_event_filter_set(UINT filter)
+{
+
+ /* Apply the user event filter. */
+ _tx_el_event_filter = filter;
+}
+
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_ghs.c b/ports_arch/ARMv7-M/threadx/ghs/src/tx_ghs.c
new file mode 100644
index 00000000..30b8054e
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_ghs.c
@@ -0,0 +1,485 @@
+/*
+ * ThreadX C/C++ Library Support
+ *
+ * Copyright 1983-2019 Green Hills Software LLC.
+ *
+ * This program is the property of Green Hills Software LLC.,
+ * its contents are proprietary information and no part of it
+ * is to be disclosed to anyone except employees of Green Hills
+ * Software LLC., or as agreed in writing signed by the President
+ * of Green Hills Software LLC.
+ */
+
+#include "tx_ghs.h"
+#ifndef TX_DISABLE_ERROR_CHECKING
+#define TX_DISABLE_ERROR_CHECKING
+#endif
+#include "tx_api.h"
+#include <setjmp.h>
+#include <string.h>
+
+/* Allow these routines to access the following ThreadX global variables. */
+extern ULONG _tx_thread_created_count;
+extern TX_THREAD *_tx_thread_created_ptr;
+extern TX_THREAD *_tx_thread_current_ptr;
+
+#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
+/* Thread-local storage routines for Green Hills releases 5.x and above. */
+/*
+ Thread-Local (Per-Thread) Library Data Retrieval
+ ================================================
+
+ __ghs_ThreadLocalStorage_specifier defines all library data items
+ that the Green Hills libraries allow to be allocated per-thread.
+
+ An implementation can choose which of these data items to allocate
+ for each thread. For example, an implementation may choose to
+ allocate an errno value for each thread, but not the strtok_saved_pos
+ pointer. The application could then use strtok_r instead of strtok for
+ correct operation.
+
+ To add per-thread library data, define one of the
+ TX_THREAD_EXTENSION_* macros in tx_port.h to include the data item
+ or items in each thread control block TX_THREAD.
+
+ If C++ with exceptions is being used, the __eh_globals entry must be
+ allocated for each thread. This is typically done by default using
+ TX_THREAD_EXTENSION_1 in tx_port.h.
+
+ If __ghs_GetThreadLocalStorageItem is customized to return a
+ per-thread errno value, you should also:
+
+ * Customize the System Library for your project
+ * Define the preprocessor symbol USE_THREAD_LOCAL_ERRNO in
+ src/libsys/ind_errn.c
+
+ If you customize the System Library, you should remove ind_thrd.c
+ from the libsys.gpj subproject.
+
+ */
+
+/* Provide global __eh_globals value to support C++ exception handling
+ outside a thread context. This name also forces this module to be
+ included in the linked program instead of the ind_thrd.o module from
+ the System Library libsys.a.
+ */
+static void *__eh_globals;
+
+#pragma ghs startnomisra
+void *__ghs_GetThreadLocalStorageItem(int specifier)
+{
+ void *ptlsitem = (void *)0;
+ switch (specifier) {
+ case (int)__ghs_TLS_Errno:
+ /* Set ptslsitem to the address of the per-thread errno value.
+ The per-thread errno value should have the type int.
+
+ If returning a per-thread errno value, follow the steps
+ above.
+
+ This item is used by numerous library functions.
+ */
+ break;
+ case (int)__ghs_TLS_SignalHandlers:
+ /* Set ptslsitem to the address of the per-thread SignalHandlers
+ array. The per-thread SignalHandlers array should have the
+ array type as in the following declaration:
+ SignalHandler SignalHandlers[_SIGMAX];
+ The SignalHandler type and _SIGMAX constant are defined in
+ ind_thrd.h.
+
+ This item is used by the library functions signal() and
+ raise().
+ */
+ break;
+ case (int)__ghs_TLS_asctime_buff:
+ /* Set ptslsitem to the address of the per-thread asctime_buff
+ array. The per-thread asctime_buff array should have the
+ array type as in the following declaration:
+ char asctime_buff[30];
+
+ This item is used by the library functions asctime() and
+ ctime(). The library provides asctime_r() and ctime_r(),
+ inherently thread-safe versions of these functions.
+ */
+ break;
+ case (int)__ghs_TLS_tmpnam_space:
+ /* Set ptslsitem to the address of the per-thread tmpnam_space
+ array. The per-thread tmpnam_space array should have the
+ array type as in the following declaration:
+ char tmpnam_space[L_tmpnam];
+ The constant is defined in <stdio.h>
+
+ This item is used by the library function tmpnam() when
+ passed NULL. The library provides tmpnam_r(), an
+ inherently thread-safe version of tmpnam().
+ */
+ break;
+ case (int)__ghs_TLS_strtok_saved_pos:
+ /* Set ptslsitem to the address of the per-thread
+ strtok_saved_pos pointer. The per-thread strtok_saved_pos
+ pointer should have the type "char *".
+
+ This item is used by the library function strtok().
+ The library provides strtok_r(), an inherently thread-safe
+ version of strtok().
+ */
+ break;
+ case (int)__ghs_TLS_gmtime_temp:
+ /* Set ptslsitem to the address of the per-thread gmtime_temp
+ value. The per-thread gmtime_temp value should have the
+ type "struct tm" defined in time.h, included by indos.h.
+
+ This item is used by the library functions gmtime() and
+ localtime(). The library provides gmtime_r() and
+ localtime_r(), inherently thread-safe versions of these
+ functions.
+ */
+ break;
+ case (int)__ghs_TLS___eh_globals:
+ /* Set ptslsitem to the address of the per-thread __eh_globals
+ value. The per-thread __eh_globals value should have the
+ type "void *".
+
+ This item is used by C++ exception handling.
+ */
+ if (_tx_thread_current_ptr)
+ ptlsitem = (void *)&(_tx_thread_current_ptr->tx_thread_eh_globals);
+ else
+ /* Use the global __eh_globals pointer. */
+ ptlsitem = (void *)&__eh_globals;
+ break;
+ }
+ return ptlsitem;
+}
+#pragma ghs endnomisra
+#else
+/* Thread-local storage routines for Green Hills releases 4.x and 3.x . */
+
+/*
+ * ThreadX C and C++ thread-safe library support routines.
+ *
+ * This implementation merely tries to guarantee thread safety within
+ * individual C library calls such as malloc() and free(), but it does
+ * not attempt to solve the problems associated with the following
+ * multithreaded issues:
+ *
+ * 1. Use of errno. This can be made thread-safe by adding errno
+ * to TX_THREAD_PORT_EXTENSION and using that within a modified
+ * version of libsys/ind_errno.c.
+ *
+ * 2. Thread safety ACROSS library calls. Certain C library calls either
+ * return pointers to statically-allocated data structures or maintain
+ * state across calls. These include strtok(), asctime(), gmtime(),
+ * tmpnam(NULL), signal(). To make such C library routines thread-safe
+ * would require adding a ThreadLocalStorage struct to the thread control
+ * block TX_THREAD. Since relatively few applications make use of these
+ * library routines, the implementation provided here uses a single, global
+ * ThreadLocalStorage data structure rather than greatly increasing the size
+ * of the thread control block TX_THREAD.
+ *
+ * The ThreadX global variable _tx_thread_current_ptr points to the
+ * current thread's control block TX_THREAD. If a ThreadLocalStorage struct
+ * called tx_tls is placed in TX_THREAD, the function GetThreadLocalStorage
+ * should be modified to return &(_tx_thread_current_ptr->tx_tls).
+ */
+
+static ThreadLocalStorage GlobalTLS;
+
+ThreadLocalStorage *GetThreadLocalStorage()
+{
+ return &GlobalTLS;
+}
+#endif
+
+/*
+ * Use a global ThreadX mutex to implement thread safety within C and C++
+ * library routines.
+ *
+ */
+TX_MUTEX __ghLockMutex;
+
+/*
+ * Acquire general lock. Blocks until the lock becomes available.
+ * Use tx_mutex_get to implement __ghsLock
+ */
+void __ghsLock(void)
+{
+ tx_mutex_get(&__ghLockMutex, TX_WAIT_FOREVER);
+}
+
+/*
+ * Release general lock
+ * Use tx_mutex_put to implement __ghsUnlock
+ */
+void __ghsUnlock(void)
+{
+ tx_mutex_put(&__ghLockMutex);
+}
+
+/* ThreadX Initialization function prototype. */
+void _tx_initialize_kernel_setup(void);
+
+void __gh_lock_init(void)
+{
+ /* Initialize the low-level portions of ThreadX. */
+ _tx_initialize_kernel_setup();
+
+ /* Create the global thread lock mutex. */
+ tx_mutex_create(&__ghLockMutex, "__ghLockMutex", TX_NO_INHERIT);
+}
+
+/*
+ Saving State Across setjmp() Calls
+ ==================================
+
+ These routines can be used to save and restore arbitrary state
+ across calls to setjmp() and longjmp().
+*/
+int __ghs_SaveSignalContext(jmp_buf jmpbuf)
+{
+ return 0;
+}
+
+/* Restore arbitrary state across a longjmp() */
+void __ghs_RestoreSignalContext(jmp_buf jmpbuf)
+{
+}
+
+#if defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 560)
+/*
+ C++ Exception Handling
+ ======================
+
+ These routines allow C++ exceptions to be used in multiple threads.
+ The default implementation uses __ghs_GetThreadLocalStorageItem
+ to return a thread-specific __eh_globals pointer.
+
+*/
+
+/* Must be called after __cpp_exception_init() is called to allocate
+ * and initialize the per-thread exception handling structure */
+void *__get_eh_globals(void)
+{
+#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
+ return *(void **)__ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
+#else
+ if (_tx_thread_current_ptr)
+
+ /* Return thread-specific __eh_globals pointer. */
+ return _tx_thread_current_ptr->tx_thread_eh_globals;
+ else
+ /* Return the global __eh_globals pointer. */
+ return GlobalTLS.__eh_globals;
+#endif
+}
+#endif
+
+#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
+#pragma weak __cpp_exception_init
+extern void __cpp_exception_init(void **);
+#pragma weak __cpp_exception_cleanup
+extern void __cpp_exception_cleanup(void **);
+
+/* __tx_cpp_exception_init retrieves the eh_globals field from
+ thread-local storage and calls __cpp_exception_init.
+ */
+void __tx_cpp_exception_init(TX_THREAD *thread_ptr) {
+ void **peh_globals;
+ if(__cpp_exception_init) {
+ if (thread_ptr)
+ peh_globals = &(thread_ptr->tx_thread_eh_globals);
+ else
+ /* Use the global __eh_globals pointer. */
+ peh_globals = &__eh_globals;
+ __cpp_exception_init(peh_globals);
+ }
+}
+
+/* __tx_cpp_exception_cleanup retrieves the eh_globals field from
+ thread-local storage and calls __cpp_exception_cleanup.
+ */
+void __tx_cpp_exception_cleanup(TX_THREAD *thread_ptr) {
+ void **peh_globals;
+ if(__cpp_exception_cleanup) {
+ if (thread_ptr)
+ peh_globals = &(thread_ptr->tx_thread_eh_globals);
+ else
+ /* Use the global __eh_globals pointer. */
+ peh_globals = &__eh_globals;
+ __cpp_exception_cleanup(peh_globals);
+ }
+}
+
+/* __ghs_cpp_exception_init is called from ind_crt1.o to initialize
+ exceptions for the global context.
+ */
+void __ghs_cpp_exception_init() {
+ __tx_cpp_exception_init((void *)0);
+}
+
+/* __ghs_cpp_exception_cleanup is called from ind_exit.o to clean up
+ exceptions for the global context.
+ */
+void __ghs_cpp_exception_cleanup(TX_THREAD *thread_ptr) {
+ __tx_cpp_exception_cleanup((void *)0);
+}
+#endif
+
+
+/*
+ File Locks
+ ======================
+
+ These routines can be customized to implement per-file locks to allow
+ thread-safe I/O.
+
+*/
+
+/* Acquire lock for FILE *addr */
+void __ghs_flock_file(void *addr)
+{
+ tx_mutex_get((TX_MUTEX *)addr, TX_WAIT_FOREVER);
+}
+
+/* Release lock for FILE *addr */
+void __ghs_funlock_file(void *addr)
+{
+ tx_mutex_put((TX_MUTEX *)addr);
+}
+
+/* Non blocking acquire lock for FILE *addr. May return -1 if */
+/* not implemented. Returns 0 on success and nonzero otherwise. */
+int __ghs_ftrylock_file(void *addr)
+{
+ return -1;
+}
+
+/* Calls to initialize local lock data structures before they */
+/* are used. */
+void __ghs_flock_create(void **addr)
+{
+ *addr = (void *)(&__ghLockMutex);
+}
+void __ghs_flock_destroy(void *addr) {}
+
+
+/*
+ * ThreadX Peak Stack Checking support routines.
+ *
+ * All of these routines are called by MULTI's ThreadX-aware debugging
+ * package to determine the peak stack use for one thread or for all threads.
+ *
+ * These routines are included in this file in order to guarantee that they will
+ * be available while debugging with MULTI. These routines are not referenced by
+ * any other part of the ThreadX system.
+ *
+ * _txs_thread_stack_check: return the peak stack usage for a thread.
+ *
+ * _txs_thread_stack_check_2: store the peak stack usage for all threads
+ * in the tx_thread_stack_size field of each thread
+ * control block, TX_THREAD. This routine takes
+ * advantage of the redundancy within the TX_THREAD
+ * structure since tx_thread_stack_size can be computed
+ * from the tx_thread_stack_start and tx_thread_stack_end
+ * fields of TX_THREAD.
+ *
+ * _txs_thread_stack_check_2_fixup: clean up from the _txs_thread_stack_check_2
+ * call by computing the stack size for each
+ * thread and storing the result in the
+ * tx_thread_stack_size field of each thread control
+ * block TX_THREAD.
+ *
+ * These three routines do not support architectures such as i960 or StarCore
+ * where the stack grows up instead of down.
+ *
+ */
+#ifndef TX_DISABLE_STACK_CHECKING
+
+ULONG _txs_thread_stack_check(TX_THREAD *thread_ptr)
+{
+ CHAR *cp; /* Pointer inside thread's stack. */
+
+ /* Search through the thread's stack to find the highest address modified. */
+ for ( cp = (CHAR *)thread_ptr->tx_thread_stack_start;
+ cp <= (CHAR *)thread_ptr->tx_thread_stack_end; ++cp ) {
+
+ /* Check if this byte in the stack contains something other than TX_STACK_FILL. */
+ if (*cp != (char)TX_STACK_FILL) {
+
+ /* Assume cp points to the locating marking the peak stack use.
+ Return the number of bytes from cp up to and including the
+ end of the stack. */
+ return (((ULONG)thread_ptr->tx_thread_stack_end) - (ULONG)cp + 1);
+ }
+ }
+ return thread_ptr->tx_thread_stack_size;
+}
+
+
+int _txs_thread_stack_check_2(void) {
+ CHAR * cp; /* Pointer inside thread's stack. */
+ TX_THREAD * tp; /* Pointer to each thread. */
+
+ /* If no threads are created, return immediately. */
+ if (!_tx_thread_created_count)
+ return 0;
+
+ /* Start iterating through the threads in the system. Assume that we always
+ have at least one thread (the system timer thread) in the system. */
+ tp = _tx_thread_created_ptr;
+
+ do {
+
+ /* Search through the thread's stack to find the highest address modified. */
+ for ( cp = (CHAR *)tp->tx_thread_stack_start; cp <= (CHAR *)tp->tx_thread_stack_end;
+ ++cp ) {
+
+ /* Check if this byte in the stack contains something other than TX_STACK_FILL. */
+ if (*cp != (char)TX_STACK_FILL) {
+
+ /* Assume cp points to the locating marking the peak stack use.
+ Store the number of bytes from cp up to and including the
+ end of the stack in the tx_thread_stack_size field. */
+ tp->tx_thread_stack_size = ((ULONG)tp->tx_thread_stack_end) - (ULONG)cp + 1;
+ break;
+ }
+
+ }
+
+ /* Continue with the next thread. */
+ tp = tp->tx_thread_created_next;
+
+ /* Loop until we point to the first thread again. */
+ } while ( tp != _tx_thread_created_ptr );
+
+ return 0;
+}
+
+int _txs_thread_stack_check_2_fixup(void) {
+ TX_THREAD * tp; /* Pointer to each thread. */
+
+ /* If no threads are created, return immediately. */
+ if (!_tx_thread_created_count)
+ return 0;
+
+ /* Start iterating through the threads in the system. Assume that we always
+ have at least one thread (the system timer thread) in the system. */
+ tp = _tx_thread_created_ptr;
+
+ do {
+
+ /* Compute the tx_thread_stack_size field by using the tx_thread_stack_end and
+ tx_thread_stack_start fields. */
+ tp->tx_thread_stack_size = (ULONG)tp->tx_thread_stack_end-(ULONG)tp->tx_thread_stack_start+1;
+
+ /* Continue with the next thread. */
+ tp = tp->tx_thread_created_next;
+
+ /* Loop until we point to the first thread again. */
+ } while ( tp != _tx_thread_created_ptr );
+
+ return 0;
+}
+
+#endif /* TX_DISABLE_STACK_CHECKING */
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_ghse.c b/ports_arch/ARMv7-M/threadx/ghs/src/tx_ghse.c
new file mode 100644
index 00000000..6369df77
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_ghse.c
@@ -0,0 +1,49 @@
+/*
+ * ThreadX C++ Library Support
+ *
+ * Copyright 1983-2019 Green Hills Software LLC.
+ *
+ * This program is the property of Green Hills Software LLC.,
+ * its contents are proprietary information and no part of it
+ * is to be disclosed to anyone except employees of Green Hills
+ * Software LLC., or as agreed in writing signed by the President
+ * of Green Hills Software LLC.
+ */
+#include "tx_ghs.h"
+#ifndef TX_DISABLE_ERROR_CHECKING
+#define TX_DISABLE_ERROR_CHECKING
+#endif
+#include "tx_api.h"
+
+/*
+ C++ Exception Handling
+ ======================
+
+ These routines allow C++ exceptions to be used in multiple threads.
+ The default implementation uses __ghs_GetThreadLocalStorageItem
+ to return a thread-specific __eh_globals pointer.
+
+*/
+
+#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 560)
+#ifdef _WIN32
+/* Windows uses a different linker, so include a stub routine, never called,
+ to pull in __cpp_exception_init and __cpp_exception_cleanup */
+extern void __cpp_exception_init(void **);
+extern void __cpp_exception_cleanup(void **);
+void __tx_win32_pull_in_exceptions(void) {
+ __cpp_exception_init(0);
+ __cpp_exception_cleanup(0);
+}
+#else
+#pragma ghs reference __cpp_exception_init
+#pragma ghs reference __cpp_exception_cleanup
+#endif
+
+/* Must be called after __cpp_exception_init() is called to allocate
+ * and initialize the per-thread exception handling structure */
+void *__get_eh_globals(void)
+{
+ return *(void **)__ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
+}
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_restore.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_restore.arm
new file mode 100644
index 00000000..8358c1e6
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_restore.arm
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .globl _tx_thread_context_restore
+_tx_thread_context_restore:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ .type _tx_thread_context_restore,$function
+ .size _tx_thread_context_restore,.-_tx_thread_context_restore
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_save.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_save.arm
new file mode 100644
index 00000000..bc323ef4
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_context_save.arm
@@ -0,0 +1,80 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ .globl _tx_thread_context_save
+_tx_thread_context_save:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ /* Context is already saved - just return. */
+
+ BX lr
+// }
+ .type _tx_thread_context_save,$function
+ .size _tx_thread_context_save,.-_tx_thread_context_save
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_control.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_control.arm
new file mode 100644
index 00000000..527beda7
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_control.arm
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ .globl _tx_thread_interrupt_control
+_tx_thread_interrupt_control:
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+ BX lr // Return to caller
+// }
+ .type _tx_thread_interrupt_control,$function
+ .size _tx_thread_interrupt_control,.-_tx_thread_interrupt_control
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_disable.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_disable.arm
new file mode 100644
index 00000000..0ef5aa92
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_disable.arm
@@ -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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ .globl _tx_thread_interrupt_disable
+_tx_thread_interrupt_disable:
+
+ /* Return current interrupt lockout posture. */
+ MRS r0, PRIMASK
+ CPSID i
+ BX lr
+// }
+ .type _tx_thread_interrupt_disable,$function
+ .size _tx_thread_interrupt_disable,.-_tx_thread_interrupt_disable
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_restore.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_restore.arm
new file mode 100644
index 00000000..96fca141
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_interrupt_restore.arm
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ .globl _tx_thread_interrupt_restore
+_tx_thread_interrupt_restore:
+
+ /* Restore previous interrupt lockout posture. */
+ MSR PRIMASK, r0
+ BX lr
+// }
+ .type _tx_thread_interrupt_restore,$function
+ .size _tx_thread_interrupt_restore,.-_tx_thread_interrupt_restore
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_schedule.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_schedule.arm
new file mode 100644
index 00000000..6b7d5295
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_schedule.arm
@@ -0,0 +1,291 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .globl _tx_thread_schedule
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+
+#ifdef __VFP__
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+
+ .type _tx_thread_schedule,$function
+ .size _tx_thread_schedule,.-_tx_thread_schedule
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ .globl PendSV_Handler
+ .globl __tx_PendSVHandler
+PendSV_Handler:
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+ CPSID i // Disable interrupts
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+ CPSIE i // Enable interrupts
+#endif
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __VFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STR.W LR, [r12, #-0x4]! // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+ CPSID i // Disable interrupts
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+ CPSIE i // Enable interrupts
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDR.W LR, [r12], #4 // Pickup LR
+#ifdef __VFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+ CPSID i // Disable interrupts
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+ CPSIE i // Enable interrupts
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+
+ CPSIE i // Enable interrupts
+ B __tx_ts_restore // Restore the thread
+// }
+
+ .type __tx_PendSVHandler,$function
+ .size __tx_PendSVHandler,.-__tx_PendSVHandler
+
+#ifdef __VFP__
+
+ .globl tx_thread_fpu_enable
+tx_thread_fpu_enable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+ .type tx_thread_fpu_enable,$function
+ .size tx_thread_fpu_enable,.-tx_thread_fpu_enable
+
+ .global tx_thread_fpu_disable
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+ .type tx_thread_fpu_disable,$function
+ .size tx_thread_fpu_disable,.-tx_thread_fpu_disable
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_stack_build.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_stack_build.arm
new file mode 100644
index 00000000..7c2783a2
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_stack_build.arm
@@ -0,0 +1,133 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .globl _tx_thread_stack_build
+_tx_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
+ .type _tx_thread_stack_build,$function
+ .size _tx_thread_stack_build,.-_tx_thread_stack_build
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_system_return.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_system_return.arm
new file mode 100644
index 00000000..123d7f50
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_system_return.arm
@@ -0,0 +1,86 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ .globl _tx_thread_system_return
+_tx_thread_system_return:
+
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+_isr_context:
+ BX lr // Return to caller
+// }
+ .type _tx_thread_system_return,$function
+ .size _tx_thread_system_return,.-_tx_thread_system_return
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/tx_timer_interrupt.arm b/ports_arch/ARMv7-M/threadx/ghs/src/tx_timer_interrupt.arm
new file mode 100644
index 00000000..edafb2a1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/tx_timer_interrupt.arm
@@ -0,0 +1,241 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mx/GHS */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+ .globl _tx_timer_interrupt
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ STMDB sp!, {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+
+// }
+ .type _tx_timer_interrupt,$function
+ .size _tx_timer_interrupt,.-_tx_timer_interrupt
diff --git a/ports_arch/ARMv7-M/threadx/ghs/src/txr_ghs.c b/ports_arch/ARMv7-M/threadx/ghs/src/txr_ghs.c
new file mode 100644
index 00000000..19572e2b
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/ghs/src/txr_ghs.c
@@ -0,0 +1,84 @@
+/*
+ * ThreadX API Runtime Error Support
+ *
+ * Copyright 1983-2019 Green Hills Software LLC.
+ *
+ * This program is the property of Green Hills Software LLC.,
+ * its contents are proprietary information and no part of it
+ * is to be disclosed to anyone except employees of Green Hills
+ * Software LLC., or as agreed in writing signed by the President
+ * of Green Hills Software LLC.
+ */
+
+/* #include "tx_ghs.h" */
+#ifndef TX_DISABLE_ERROR_CHECKING
+#define TX_DISABLE_ERROR_CHECKING
+#endif
+#include "tx_api.h"
+
+/* Customized ThreadX API runtime error support routine. */
+
+void _rnerr(int num, int linenum, const char*str, void*ptr, ...);
+
+/* __ghs_rnerr()
+ This is the custom runtime error checking routine.
+ This implementation uses the existing __rnerr() routine.
+ Another implementation could use the .syscall mechanism,
+ provided MULTI was modified to understand that.
+ */
+void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hexVal) {
+ TX_INTERRUPT_SAVE_AREA
+ int num;
+ /*
+ Initialize the stack levels value.
+
+ Add 3 to account for the calls to _rnerr, __rnerr, and
+ __ghs_rnerr.
+
+ If the implementation changes, calls to __ghs_rnerr
+ will not need to be changed.
+
+ Zero is not permitted, so substitute 3 in that case.
+ */
+ num = (stackLevels+3) & 0xf;
+ if (!num) {
+ num = 3;
+ }
+ /*
+ Shift the stack levels value to bits 12..15 and
+ insert the stack trace display value in bit 11.
+ Bits 0..10 are unused.
+ */
+ num = (num << 12) | (stackTraceDisplay ? 0x800 : 0);
+
+ /* This will mask all interrupts in the RTEC code, which is probably
+ unacceptable for many targets. */
+ TX_DISABLE
+ _rnerr(num, -1, (const char *)hexVal, (void *)errMsg);
+ TX_RESTORE
+}
+
+
+/* ThreadX thread stack checking runtime support routine. */
+
+extern char __ghsbegin_stack[];
+extern TX_THREAD *_tx_thread_current_ptr;
+
+void __stkchk(void) {
+ int i;
+ if(_tx_thread_current_ptr)
+ {
+ if((unsigned)(&i) <=
+ (unsigned)(_tx_thread_current_ptr -> tx_thread_stack_start))
+ {
+ _rnerr(21, -1, 0, 0);
+ }
+ }
+ else
+ {
+ if((unsigned)(&i) <= (unsigned)__ghsbegin_stack)
+ {
+ _rnerr(21, -1, 0, 0);
+ }
+ }
+}
diff --git a/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt b/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt
new file mode 100644
index 00000000..ab9464d2
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt
@@ -0,0 +1,18 @@
+
+target_sources(${PROJECT_NAME} PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${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.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S
+ ${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
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME} PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx.bat b/ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx.bat
new file mode 100644
index 00000000..f5545692
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx.bat
@@ -0,0 +1,230 @@
+del tx.a
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_stack_build.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_schedule.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_system_return.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_context_save.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_context_restore.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_interrupt_control.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_interrupt_disable.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_interrupt_restore.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_timer_interrupt.S
+
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_search.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_set.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_set_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_high_level.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_kernel_enter.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_kernel_setup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_priority_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_flush.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_front_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_receive.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_send_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_ceiling_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_put_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_entry_exit_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_identify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_preemption_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_priority_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_relinquish.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_reset.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_resume.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_shell_entry.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_sleep.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_analyze.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_error_handler.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_error_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_suspend.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_preempt_check.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_resume.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_suspend.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_terminate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_time_slice.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_time_slice_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_timeout.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_wait_abort.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_time_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_time_set.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_activate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_deactivate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_expiration_process.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_system_activate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_system_deactivate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_thread_entry.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_buffer_full_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_enable.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_event_filter.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_event_unfilter.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_disable.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_interrupt_control.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_isr_enter_insert.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_isr_exit_insert.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_object_register.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_object_unregister.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_user_event_insert.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_set.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_set_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_flush.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_front_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_receive.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_send_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_ceiling_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_put_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_entry_exit_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_preemption_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_priority_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_relinquish.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_reset.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_resume.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_suspend.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_terminate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_time_slice_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_wait_abort.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_activate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_deactivate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_info_get.c
+
+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_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_arch/ARMv7-M/threadx/gnu/example_build/build_threadx_sample.bat b/ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx_sample.bat
new file mode 100644
index 00000000..ee3f0008
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx_sample.bat
@@ -0,0 +1,5 @@
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb cortexm4_vectors.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb cortexm4_crt0.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb tx_initialize_low_level.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc sample_threadx.c
+arm-none-eabi-gcc -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -T sample_threadx.ld -ereset_handler -nostartfiles -o sample_threadx.out -Wl,-Map=sample_threadx.map cortexm4_vectors.o cortexm4_crt0.o tx_initialize_low_level.o sample_threadx.o tx.a
diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_crt0.S b/ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_crt0.S
new file mode 100644
index 00000000..4228fc11
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_crt0.S
@@ -0,0 +1,91 @@
+ .syntax unified
+ .section .init, "ax"
+ .code 16
+ .align 2
+ .thumb_func
+
+ .global _start
+_start:
+ CPSID i
+ ldr r1, =__stack_end__
+ mov sp, r1
+
+ /* Copy initialised sections into RAM if required. */
+ ldr r0, =__data_load_start__
+ ldr r1, =__data_start__
+ ldr r2, =__data_end__
+ bl crt0_memory_copy
+
+ /* Zero bss. */
+ ldr r0, =__bss_start__
+ ldr r1, =__bss_end__
+ mov r2, #0
+ bl crt0_memory_set
+
+ /* Setup heap - not recommended for Threadx but here for compatibility reasons */
+ ldr r0, = __heap_start__
+ ldr r1, = __heap_end__
+ sub r1, r1, r0
+ mov r2, #0
+ str r2, [r0]
+ add r0, r0, #4
+ str r1, [r0]
+
+ /* constructors in case of using C++ */
+ ldr r0, =__ctors_start__
+ ldr r1, =__ctors_end__
+crt0_ctor_loop:
+ cmp r0, r1
+ beq crt0_ctor_end
+ ldr r2, [r0]
+ add r0, #4
+ push {r0-r1}
+ blx r2
+ pop {r0-r1}
+ b crt0_ctor_loop
+crt0_ctor_end:
+
+ /* Setup call frame for main() */
+ mov r0, #0
+ mov lr, r0
+ mov r12, sp
+
+start:
+ /* Jump to main() */
+ mov r0, #0
+ mov r1, #0
+ ldr r2, =main
+ blx r2
+ /* when main returns, loop forever. */
+crt0_exit_loop:
+ b crt0_exit_loop
+
+ /* Startup helper functions. */
+
+crt0_memory_copy:
+ cmp r0, r1
+ beq memory_copy_done
+memory_copy_loop:
+ ldrb r3, [r0]
+ add r0, r0, #1
+ strb r3, [r1]
+ add r1, r1, #1
+ cmp r1, r2
+ bne memory_copy_loop
+memory_copy_done:
+ bx lr
+
+crt0_memory_set:
+ cmp r0, r1
+ beq memory_set_done
+ strb r2, [r0]
+ add r0, r0, #1
+ b crt0_memory_set
+memory_set_done:
+ bx lr
+
+ /* Setup attibutes of stack and heap sections so they don't take up room in the elf file */
+ .section .stack, "wa", %nobits
+ .section .stack_process, "wa", %nobits
+ .section .heap, "wa", %nobits
+ \ No newline at end of file
diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_vectors.S b/ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_vectors.S
new file mode 100644
index 00000000..714944d5
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_vectors.S
@@ -0,0 +1,77 @@
+ .global reset_handler
+
+ .global __tx_NMIHandler
+ .global __tx_BadHandler
+ .global __tx_SVCallHandler
+ .global __tx_DBGHandler
+ .global PendSV_Handler
+ .global __tx_SysTickHandler
+ .global __tx_BadHandler
+
+ .syntax unified
+ .section .vectors, "ax"
+ .code 16
+ .align 0
+ .global _vectors
+
+_vectors:
+ .word __stack_end__
+ .word reset_handler
+ .word __tx_NMIHandler
+ .word __tx_HardfaultHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word 0 // Reserved
+ .word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
+ .word __tx_DBGHandler
+ .word 0 // Reserved
+ .word PendSV_Handler
+ .word __tx_SysTickHandler // Used by Threadx timer functionality
+ .word __tx_BadHandler // Populate with user Interrupt handler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+ .word __tx_BadHandler
+
+ .section .init, "ax"
+ .thumb_func
+reset_handler:
+ // low level hardware config, such as PLL setup goes here
+ b _start
+
+
+
diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.c b/ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.c
new file mode 100644
index 00000000..597f373c
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.c
@@ -0,0 +1,370 @@
+/* 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 "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;
+ }
+}
+
+
+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_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.ld b/ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.ld
new file mode 100644
index 00000000..c65a1346
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.ld
@@ -0,0 +1,125 @@
+MEMORY
+{
+ RAM (wx) : ORIGIN = 0x20000000, LENGTH = 0x00800000
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00400000
+}
+
+__STACKSIZE__ = 1024;
+__STACKSIZE_PROCESS__ = 0;
+__HEAPSIZE__ = 128;
+
+SECTIONS
+{
+ .vectors :
+ {
+ KEEP(*(.vectors .vectors.*))
+ } > FLASH
+
+ .text :
+ {
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ __ctors_start__ = ALIGN(4);
+ *(SORT(.ctors.*))
+ *(.ctors)
+ __ctors_end__ = ALIGN(4);
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ __dtors_start__ = ALIGN(4);
+ *(SORT(.dtors.*))
+ *(.dtors)
+ __dtors_end__ = ALIGN(4);
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ __data_load_start__ = ALIGN (4);
+
+ .data : AT (__data_load_start__)
+ {
+ __data_start__ = .;
+
+ *(vtable)
+ *(.data*)
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+
+ __data_end__ = .;
+
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+
+ } > RAM
+
+ .heap (COPY):
+ {
+ __heap_start__ = ALIGN(4);
+ *(.heap)
+ . = ALIGN(. + __HEAPSIZE__, 4);
+ __heap_end__ = ALIGN(4);
+ } > RAM
+
+ .stack ALIGN(4) (NOLOAD) :
+ {
+ __stack_start__ = ALIGN(4);
+ *(.stack)
+ . = ALIGN(. + __STACKSIZE__, 4);
+ __stack_end__ = ALIGN(4);
+ } > RAM
+
+ __RAM_segment_used_end__ = .;
+}
diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S
new file mode 100644
index 00000000..fc987ce3
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.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 */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .global _tx_thread_system_stack_ptr
+ .global _tx_initialize_unused_memory
+ .global __RAM_segment_used_end__
+ .global _tx_timer_interrupt
+ .global __main
+ .global _vectors
+ .global __tx_NMIHandler // NMI
+ .global __tx_BadHandler // HardFault
+ .global __tx_SVCallHandler // SVCall
+ .global __tx_DBGHandler // Monitor
+ .global __tx_PendSVHandler // PendSV
+ .global __tx_SysTickHandler // SysTick
+ .global __tx_IntHandler // Int 0
+
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mx/GNU */
+/* 6.1.10 */
+/* 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ .global _tx_initialize_low_level
+ .thumb_func
+_tx_initialize_low_level:
+
+ /* Ensure that interrupts are disabled. */
+ CPSID i
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ LDR r1, =__RAM_segment_used_end__ // Build first free address
+ ADD r1, r1, #4 //
+ STR r1, [r0] // Setup first unused memory pointer
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =_vectors // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =_vectors // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+#ifndef TX_NO_TIMER
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+#endif
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+/* Define shells for each of the unused vectors. */
+ .global __tx_BadHandler
+ .thumb_func
+__tx_BadHandler:
+ B __tx_BadHandler
+
+/* added to catch the hardfault */
+ .global __tx_HardfaultHandler
+ .thumb_func
+__tx_HardfaultHandler:
+ B __tx_HardfaultHandler
+
+/* added to catch the SVC */
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_SVCallHandler:
+ B __tx_SVCallHandler
+
+/* Generic interrupt handler template */
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+// VOID InterruptHandler (VOID)
+// {
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ /* Do interrupt handler work here */
+ /* BL <your C Function>.... */
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+
+#ifndef TX_NO_TIMER
+/* System Tick timer interrupt handler */
+ .global __tx_SysTickHandler
+ .global SysTick_Handler
+ .thumb_func
+__tx_SysTickHandler:
+ .thumb_func
+SysTick_Handler:
+// VOID SysTick_Handler (VOID)
+// {
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+#endif
+
+/* NMI, DBG handlers */
+ .global __tx_NMIHandler
+ .thumb_func
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+ .global __tx_DBGHandler
+ .thumb_func
+__tx_DBGHandler:
+ B __tx_DBGHandler
diff --git a/ports_arch/ARMv7-M/threadx/gnu/readme_threadx.txt b/ports_arch/ARMv7-M/threadx/gnu/readme_threadx.txt
new file mode 100644
index 00000000..d9063d65
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/readme_threadx.txt
@@ -0,0 +1,209 @@
+ Microsoft's Azure RTOS ThreadX for ARMv7-M
+ (Cortex-M3, Cortex-M4, Cortex-M7)
+ Using the GNU Tools
+
+
+1. Building the ThreadX run-time Library
+
+Navigate to the "example_build" directory. Ensure that
+you have setup your path and other environment variables necessary for the ARM
+GNU compiler. At this point you may run the build_threadx.bat batch file.
+This will build the ThreadX run-time environment in the "example_build"
+directory.
+
+You should observe assembly and compilation of a series of ThreadX source
+files. At the end of the batch file, they are all combined into the
+run-time library file: tx.a. This file must be linked with your
+application in order to use ThreadX.
+
+
+2. Demonstration System
+
+The ThreadX demonstration is designed to execute on Cortex-M evaluation boards
+or on a dedicated simulator.
+
+Building the demonstration is easy, simply execute the build_threadx_sample.bat
+batch file while inside the "example_build" directory.
+
+You should observe the compilation of sample_threadx.c (which is the demonstration
+application) and linking with tx.a. The resulting file sample_threadx.out is a binary
+file that can be downloaded and executed on the a simulator, or downloaded to a board.
+
+
+3. System Initialization
+
+The entry point in ThreadX for the Cortex-M using gnu tools uses the standard GNU
+Cortex-M reset sequence. From the reset vector the C runtime will be initialized.
+
+The ThreadX tx_initialize_low_level.S file is responsible for setting up
+various system data structures, the vector area, and a periodic timer interrupt
+source.
+
+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.
+
+
+4. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-M version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+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 it run faster,
+you can change the build_threadx.bat file to remove the -g option and enable
+all compiler 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.
+
+
+6. Interrupt Handling
+
+ThreadX provides complete and high-performance interrupt handling for Cortex-M
+targets. There are a certain set of requirements that are defined in the
+following sub-sections:
+
+
+6.1 Vector Area
+
+The Cortex-M vectors start at the label __tx_vectors or similar. The application may modify
+the vector area according to its needs. There is code in tx_initialize_low_level() that will
+configure the vector base register.
+
+
+6.2 Managed Interrupts
+
+A ThreadX managed interrupt is defined below. By following these conventions, the
+application ISR is then allowed access to various ThreadX services from the ISR.
+Here is the standard template for managed ISRs in ThreadX:
+
+
+ .global __tx_IntHandler
+ .thumb_func
+__tx_IntHandler:
+; VOID InterruptHandler (VOID)
+; {
+ PUSH {r0, lr}
+
+; /* Do interrupt handler work here */
+; /* BL <your interrupt routine in C> */
+
+ POP {r0, lr}
+ BX lr
+; }
+
+
+Note: the Cortex-M requires exception handlers to be thumb labels, this implies bit 0 set.
+To accomplish this, the declaration of the label has to be preceded by the assembler directive
+.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
+be inserted in the correct location in the interrupt vector table. This table is typically
+located in either your runtime startup file or in the tx_initialize_low_level.S file.
+
+
+7. FPU Support
+
+ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context - no additional setup by the application.
+
+
+8. 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:
+
+06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using GNU tools.
+
+
+Copyright(c) 1996-2021 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_misra.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_misra.S
new file mode 100644
index 00000000..c84d8576
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_misra.S
@@ -0,0 +1,723 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ #define SHT_PROGBITS 0x1
+
+ .global __aeabi_memset
+ .global _tx_thread_current_ptr
+ .global _tx_thread_interrupt_disable
+ .global _tx_thread_interrupt_restore
+ .global _tx_thread_stack_analyze
+ .global _tx_thread_stack_error_handler
+ .global _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_trace_buffer_current_ptr
+ .global _tx_trace_buffer_end_ptr
+ .global _tx_trace_buffer_start_ptr
+ .global _tx_trace_event_enable_bits
+ .global _tx_trace_full_notify_function
+ .global _tx_trace_header_ptr
+#endif
+
+ .global _tx_misra_always_true
+ .global _tx_misra_block_pool_to_uchar_pointer_convert
+ .global _tx_misra_byte_pool_to_uchar_pointer_convert
+ .global _tx_misra_char_to_uchar_pointer_convert
+ .global _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_indirect_void_to_uchar_pointer_convert
+ .global _tx_misra_memset
+ .global _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_object_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_pointer_to_ulong_convert
+ .global _tx_misra_status_get
+ .global _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_time_stamp_get
+#endif
+ .global _tx_misra_timer_indirect_to_void_pointer_convert
+ .global _tx_misra_timer_pointer_add
+ .global _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_trace_event_insert
+#endif
+ .global _tx_misra_uchar_pointer_add
+ .global _tx_misra_uchar_pointer_dif
+ .global _tx_misra_uchar_pointer_sub
+ .global _tx_misra_uchar_to_align_type_pointer_convert
+ .global _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_entry_pointer_convert
+ .global _tx_misra_uchar_to_header_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ .global _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_object_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_void_pointer_convert
+ .global _tx_misra_ulong_pointer_add
+ .global _tx_misra_ulong_pointer_dif
+ .global _tx_misra_ulong_pointer_sub
+ .global _tx_misra_ulong_to_pointer_convert
+ .global _tx_misra_ulong_to_thread_pointer_convert
+ .global _tx_misra_user_timer_pointer_get
+ .global _tx_misra_void_to_block_pool_pointer_convert
+ .global _tx_misra_void_to_byte_pool_pointer_convert
+ .global _tx_misra_void_to_event_flags_pointer_convert
+ .global _tx_misra_void_to_indirect_uchar_pointer_convert
+ .global _tx_misra_void_to_mutex_pointer_convert
+ .global _tx_misra_void_to_queue_pointer_convert
+ .global _tx_misra_void_to_semaphore_pointer_convert
+ .global _tx_misra_void_to_thread_pointer_convert
+ .global _tx_misra_void_to_uchar_pointer_convert
+ .global _tx_misra_void_to_ulong_pointer_convert
+ .global _tx_misra_ipsr_get
+ .global _tx_misra_control_get
+ .global _tx_misra_control_set
+#ifdef __ARM_FP
+ .global _tx_misra_fpccr_get
+ .global _tx_misra_vfp_touch
+#endif
+
+ .global _tx_misra_event_flags_group_not_used
+ .global _tx_misra_event_flags_set_notify_not_used
+ .global _tx_misra_queue_not_used
+ .global _tx_misra_queue_send_notify_not_used
+ .global _tx_misra_semaphore_not_used
+ .global _tx_misra_semaphore_put_notify_not_used
+ .global _tx_misra_thread_entry_exit_notify_not_used
+ .global _tx_misra_thread_not_used
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+ .syntax unified
+ .thumb_func
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ .text
+ .thumb_func
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N _tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N _tx_misra_message_copy_1
+_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N _tx_misra_message_copy_2
+_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR R2,=0x54485244
+ CMP R1,R2
+ BNE.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_3
+_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N _tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N _tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N _tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N _tx_misra_trace_event_insert_4
+ LDR.N R0,DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N _tx_misra_trace_event_insert_0
+_tx_misra_trace_event_insert_4:
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ .data
+DataTable2_1:
+ .word _tx_trace_buffer_current_ptr
+
+ .data
+DataTable2_2:
+ .word _tx_trace_event_enable_bits
+
+ .data
+DataTable2_5:
+ .word _tx_trace_buffer_end_ptr
+
+ .data
+DataTable2_6:
+ .word _tx_trace_buffer_start_ptr
+
+ .data
+DataTable2_7:
+ .word _tx_trace_header_ptr
+
+ .data
+DataTable2_8:
+ .word _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ .data
+DataTable2_3:
+ .word _tx_thread_system_state
+
+ .data
+DataTable2_4:
+ .word _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARM_FP
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ .data
+ .word 0
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_restore.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..74c4f5de
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_exit
+#endif
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .global _tx_thread_context_restore
+ .thumb_func
+_tx_thread_context_restore:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_save.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..793810ba
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,86 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ .global _tx_thread_context_save
+ .thumb_func
+_tx_thread_context_save:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ /* Context is already saved - just return. */
+
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_control.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..adf13b13
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ .global _tx_thread_interrupt_control
+ .thumb_func
+_tx_thread_interrupt_control:
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_disable.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_disable.S
new file mode 100644
index 00000000..eb6c7250
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_disable.S
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ .global _tx_thread_interrupt_disable
+ .thumb_func
+_tx_thread_interrupt_disable:
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_restore.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_restore.S
new file mode 100644
index 00000000..ab5b4807
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_interrupt_restore.S
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ .global _tx_thread_interrupt_restore
+ .thumb_func
+_tx_thread_interrupt_restore:
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S
new file mode 100644
index 00000000..a599d9db
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,331 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+#ifdef TX_LOW_POWER
+ .global tx_low_power_enter
+ .global tx_low_power_exit
+#endif
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Fixed predefined macro name, */
+/* resulting in version 6.1.10 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+
+#ifdef __ARM_FP
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .syntax unified
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+#ifdef __ARM_FP
+
+ .global tx_thread_fpu_enable
+ .thumb_func
+tx_thread_fpu_enable:
+ .global tx_thread_fpu_disable
+ .thumb_func
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_stack_build.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..d65a483b
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .global _tx_thread_stack_build
+ .thumb_func
+_tx_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S
new file mode 100644
index 00000000..759a3f8a
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.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 */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .text 32
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ .thumb_func
+ .global _tx_thread_system_return
+_tx_thread_system_return:
+
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context:
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_timer_interrupt.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..3a276247
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,261 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ .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_thread_time_slice
+ .global _tx_timer_expiration_process
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+#ifndef TX_NO_TIMER
+ .global _tx_timer_interrupt
+ .thumb_func
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ STMDB sp!, {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/azure_rtos.eww b/ports_arch/ARMv7-M/threadx/iar/example_build/azure_rtos.eww
new file mode 100644
index 00000000..17e0d329
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/azure_rtos.eww
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<workspace>
+ <project>
+ <path>$WS_DIR$\sample_threadx.ewp</path>
+ </project>
+ <project>
+ <path>$WS_DIR$\tx.ewp</path>
+ </project>
+ <batchBuild/>
+</workspace>
+
+
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/cstartup_M.s b/ports_arch/ARMv7-M/threadx/iar/example_build/cstartup_M.s
new file mode 100644
index 00000000..8b7fbc0d
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/cstartup_M.s
@@ -0,0 +1,72 @@
+ EXTERN __iar_program_start
+ PUBLIC __vector_table
+
+ SECTION .text:CODE:REORDER(1)
+
+ ;; Keep vector table even if it's not referenced
+ REQUIRE __vector_table
+
+ THUMB
+
+ ;; Forward declaration of sections.
+ SECTION CSTACK:DATA:NOROOT(3)
+ SECTION .intvec:CODE:NOROOT(2)
+
+ DATA
+
+__vector_table
+ DCD sfe(CSTACK)
+ DCD __Reset_Vector
+ DCD NMI_Handler
+ DCD HardFault_Handler
+ DCD MemManage_Handler
+ DCD BusFault_Handler
+ DCD UsageFault_Handler
+ DCD 0
+ DCD 0
+ DCD 0
+ DCD 0
+ DCD SVC_Handler
+ DCD DebugMon_Handler
+ DCD 0
+ DCD PendSV_Handler
+ DCD SysTick_Handler
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Default interrupt handlers.
+;;
+
+ PUBWEAK NMI_Handler
+ PUBWEAK HardFault_Handler
+ PUBWEAK MemManage_Handler
+ PUBWEAK BusFault_Handler
+ PUBWEAK UsageFault_Handler
+ PUBWEAK SVC_Handler
+ PUBWEAK DebugMon_Handler
+ PUBWEAK PendSV_Handler
+ PUBWEAK SysTick_Handler
+
+ SECTION .text:CODE:REORDER:NOROOT(1)
+ THUMB
+__Reset_Vector:
+ ; CPSID i ; Disable interrupts
+ B __iar_program_start
+
+
+NMI_Handler
+HardFault_Handler
+MemManage_Handler
+BusFault_Handler
+UsageFault_Handler
+SVC_Handler
+DebugMon_Handler
+PendSV_Handler
+SysTick_Handler
+Default_Handler
+__default_handler
+ CALL_GRAPH_ROOT __default_handler, "interrupt"
+ NOCALL __default_handler
+ B __default_handler
+
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.c b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.c
new file mode 100644
index 00000000..60f5a3d3
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.c
@@ -0,0 +1,389 @@
+/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete
+ description of this demonstration. */
+
+#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;
+
+
+/* Define byte pool memory. */
+
+UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
+
+
+/* Define event buffer. */
+
+#ifdef TX_ENABLE_EVENT_TRACE
+UCHAR trace_buffer[0x10000];
+#endif
+
+
+/* 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()
+{
+
+ /* Please refer to Chapter 6 of the ThreadX User Guide for a complete
+ description of this demonstration. */
+
+
+ /* 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;
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+ tx_trace_enable(trace_buffer, sizeof(trace_buffer), 32);
+#endif
+
+ /* Create a byte memory pool from which to allocate the thread stacks. */
+ tx_byte_pool_create(&byte_pool_0, "byte pool 0", byte_pool_memory, 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;
+ }
+}
+
+
+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_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewd b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewd
new file mode 100644
index 00000000..6d7eecd6
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewd
@@ -0,0 +1,2974 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <fileVersion>3</fileVersion>
+ <configuration>
+ <name>Debug</name>
+ <toolchain>
+ <name>ARM</name>
+ </toolchain>
+ <debug>1</debug>
+ <settings>
+ <name>C-SPY</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>32</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>CInput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CEndian</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCVariant</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>MemOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MemFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>RunToEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RunToName</name>
+ <state>main</state>
+ </option>
+ <option>
+ <name>CExtraOptionsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCDDFArgumentProducer</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCDownloadSuppressDownload</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCDownloadVerifyAll</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProductVersion</name>
+ <state>5.11.0.50615</state>
+ </option>
+ <option>
+ <name>OCDynDriverList</name>
+ <state>ARMSIM_ID</state>
+ </option>
+ <option>
+ <name>OCLastSavedByProductVersion</name>
+ <state>8.50.6.28950</state>
+ </option>
+ <option>
+ <name>UseFlashLoader</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CLowLevel</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCBE8Slave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacFile2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CDevice</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>FlashLoadersV3</name>
+ <state>$TOOLKIT_DIR$\config\flashloader\</state>
+ </option>
+ <option>
+ <name>OCImagesSuppressCheck1</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesPath1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesSuppressCheck2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesPath2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesSuppressCheck3</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesPath3</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OverrideDefFlashBoard</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesOffset1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesOffset2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesOffset3</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesUse1</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesUse2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesUse3</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCDeviceConfigMacroFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCDebuggerExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCAllMTBOptions</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCMulticoreNrOfCores</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCMulticoreWorkspace</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCMulticoreSlaveProject</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCMulticoreSlaveConfiguration</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCDownloadExtraImage</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCAttachSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MassEraseBeforeFlashing</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCMulticoreNrOfCoresSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCMulticoreAMPConfigType</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCMulticoreSessionFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCTpiuBaseOption</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>ARMSIM_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCSimDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCSimEnablePSP</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCSimPspOverrideConfig</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCSimPspConfigFile</name>
+ <state></state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CADI_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>CCadiMemory</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>Fast Model</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCADILogFileCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCADILogFileEditB</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CMSISDAP_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>4</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCIarProbeScriptFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CMSISDAPResetList</name>
+ <version>1</version>
+ <state>10</state>
+ </option>
+ <option>
+ <name>CMSISDAPHWResetDuration</name>
+ <state>300</state>
+ </option>
+ <option>
+ <name>CMSISDAPHWResetDelay</name>
+ <state>200</state>
+ </option>
+ <option>
+ <name>CMSISDAPDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CMSISDAPInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiTargetEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPJtagSpeedList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPRestoreBreakpointsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPUpdateBreakpointsEdit</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>RDICatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchUndef</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchData</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchPrefetch</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchMMERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchNOCPERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchCHKERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSTATERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchBUSERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchINTERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSFERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchHARDERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiCPUEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiCPUNumber</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeCfgOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeConfig</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CMSISDAPProbeConfigRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPSelectedCPUBehaviour</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ICpuName</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCJetEmuParams</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCCMSISDAPUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCCMSISDAPUsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>GDBSERVER_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>TCPIP</name>
+ <state>aaa.bbb.ccc.ddd</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$TOOLKIT_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCJTagBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJTagDoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJTagUpdateBreakpoints</name>
+ <state>main</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>IJET_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>8</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCIarProbeScriptFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetResetList</name>
+ <version>1</version>
+ <state>10</state>
+ </option>
+ <option>
+ <name>IjetHWResetDuration</name>
+ <state>300</state>
+ </option>
+ <option>
+ <name>IjetHWResetDelay</name>
+ <state>200</state>
+ </option>
+ <option>
+ <name>IjetPowerFromProbe</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetPowerRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>IjetInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiTargetEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetScanChainNonARMDevices</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetIRLength</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetJtagSpeedList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetProtocolRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetSwoPin</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetCpuClockEdit</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IjetSwoPrescalerList</name>
+ <version>1</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetRestoreBreakpointsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetUpdateBreakpointsEdit</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>RDICatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchUndef</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchData</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchPrefetch</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchMMERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchNOCPERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchCHKERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSTATERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchBUSERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchINTERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSFERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchHARDERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeCfgOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeConfig</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IjetProbeConfigRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiCPUEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiCPUNumber</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetSelectedCPUBehaviour</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ICpuName</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCJetEmuParams</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetPreferETB</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetTraceSettingsList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetTraceSizeList</name>
+ <version>0</version>
+ <state>4</state>
+ </option>
+ <option>
+ <name>FlashBoardPathSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCIjetUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCIjetUsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>JLINK_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>16</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>CCCatchSFERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>JLinkSpeed</name>
+ <state>32</state>
+ </option>
+ <option>
+ <name>CCJLinkDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCJLinkHWResetDelay</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>JLinkInitialSpeed</name>
+ <state>32</state>
+ </option>
+ <option>
+ <name>CCDoJlinkMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCScanChainNonARMDevices</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkIRLength</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkCommRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkTCPIP</name>
+ <state>aaa.bbb.ccc.ddd</state>
+ </option>
+ <option>
+ <name>CCJLinkSpeedRadioV2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCUSBDevice</name>
+ <version>1</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCRDICatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchUndef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchData</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchPrefetch</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkDoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkUpdateBreakpoints</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>CCJLinkInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkResetList</name>
+ <version>6</version>
+ <state>7</state>
+ </option>
+ <option>
+ <name>CCJLinkInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchMMERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchNOCPERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchCHRERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchSTATERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchBUSERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchINTERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchHARDERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCJLinkScriptFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCJLinkUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCTcpIpAlt</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkTcpIpSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCCpuClockEdit</name>
+ <state>72.0</state>
+ </option>
+ <option>
+ <name>CCSwoClockAuto</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSwoClockEdit</name>
+ <state>2000</state>
+ </option>
+ <option>
+ <name>OCJLinkTraceSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCJLinkTraceSourceDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCJLinkDeviceName</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>LMIFTDI_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>2</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>LmiftdiSpeed</name>
+ <state>500</state>
+ </option>
+ <option>
+ <name>CCLmiftdiDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCLmiftdiLogFile</name>
+ <state>$TOOLKIT_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCLmiFtdiInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCLmiFtdiInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>NULINK_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>PEMICRO_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>3</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCJPEMicroShowSettings</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>STLINK_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>7</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCSTLinkInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkResetList</name>
+ <version>3</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCpuClockEdit</name>
+ <state>72.0</state>
+ </option>
+ <option>
+ <name>CCSwoClockAuto</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSwoClockEdit</name>
+ <state>2000</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCSTLinkDoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkUpdateBreakpoints</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchMMERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchNOCPERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchCHRERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchSTATERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchBUSERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchINTERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchSFERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchHARDERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCSTLinkUsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkJtagSpeedList</name>
+ <version>2</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkDAPNumber</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCSTLinkDebugAccessPortRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkUseServerSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkProbeList</name>
+ <version>1</version>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>THIRDPARTY_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>CThirdPartyDriverDll</name>
+ <state>Browse to your third-party driver</state>
+ </option>
+ <option>
+ <name>CThirdPartyLogFileCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CThirdPartyLogFileEditB</name>
+ <state>$TOOLKIT_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>TIFET_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCMSPFetResetList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetTargetVccTypeDefault</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetTargetVoltage</name>
+ <state>###Uninitialized###</state>
+ </option>
+ <option>
+ <name>CCMSPFetVCCDefault</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCMSPFetTargetSettlingtime</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetRadioJtagSpeedType</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCMSPFetConnection</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetUsbComPort</name>
+ <state>Automatic</state>
+ </option>
+ <option>
+ <name>CCMSPFetAllowAccessToBSL</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCMSPFetRadioEraseFlash</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>XDS100_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>8</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>TIPackageOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TIPackage</name>
+ <state></state>
+ </option>
+ <option>
+ <name>BoardFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCXds100BreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100DoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100UpdateBreakpoints</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>CCXds100CatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchUndef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchData</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchPrefetch</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchMMERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchNOCPERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchCHRERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchSTATERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchBUSERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchINTERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchSFERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchHARDERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CpuClockEdit</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCXds100SwoClockAuto</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100SwoClockEdit</name>
+ <state>1000</state>
+ </option>
+ <option>
+ <name>CCXds100HWResetDelay</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100ResetList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100UsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCXds100UsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100JtagSpeedList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100InterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100InterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100ProbeList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100SWOPortRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100SWOPort</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCXDSTargetVccEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXDSTargetVoltage</name>
+ <state>###Uninitialized###</state>
+ </option>
+ <option>
+ <name>OCXDSDigitalStatesConfigFile</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <debuggerPlugins>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\RemedyRtosViewer\RemedyRtosViewer.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8b.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8bBE.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin</file>
+ <loadFlag>1</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ </debuggerPlugins>
+ </configuration>
+ <configuration>
+ <name>Release</name>
+ <toolchain>
+ <name>ARM</name>
+ </toolchain>
+ <debug>0</debug>
+ <settings>
+ <name>C-SPY</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>32</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>CInput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CEndian</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCVariant</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>MemOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MemFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>RunToEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RunToName</name>
+ <state>main</state>
+ </option>
+ <option>
+ <name>CExtraOptionsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCDDFArgumentProducer</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCDownloadSuppressDownload</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCDownloadVerifyAll</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProductVersion</name>
+ <state>5.11.0.50615</state>
+ </option>
+ <option>
+ <name>OCDynDriverList</name>
+ <state>ARMSIM_ID</state>
+ </option>
+ <option>
+ <name>OCLastSavedByProductVersion</name>
+ <state></state>
+ </option>
+ <option>
+ <name>UseFlashLoader</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CLowLevel</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCBE8Slave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacFile2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CDevice</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>FlashLoadersV3</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesSuppressCheck1</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesPath1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesSuppressCheck2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesPath2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesSuppressCheck3</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesPath3</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OverrideDefFlashBoard</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesOffset1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesOffset2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesOffset3</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCImagesUse1</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesUse2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCImagesUse3</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCDeviceConfigMacroFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCDebuggerExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCAllMTBOptions</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCMulticoreNrOfCores</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCMulticoreWorkspace</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCMulticoreSlaveProject</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCMulticoreSlaveConfiguration</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCDownloadExtraImage</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCAttachSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MassEraseBeforeFlashing</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCMulticoreNrOfCoresSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCMulticoreAMPConfigType</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCMulticoreSessionFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCTpiuBaseOption</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>ARMSIM_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCSimDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCSimEnablePSP</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCSimPspOverrideConfig</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCSimPspConfigFile</name>
+ <state></state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CADI_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>CCadiMemory</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>Fast Model</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCADILogFileCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCADILogFileEditB</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CMSISDAP_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>4</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCIarProbeScriptFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CMSISDAPResetList</name>
+ <version>1</version>
+ <state>10</state>
+ </option>
+ <option>
+ <name>CMSISDAPHWResetDuration</name>
+ <state>300</state>
+ </option>
+ <option>
+ <name>CMSISDAPHWResetDelay</name>
+ <state>200</state>
+ </option>
+ <option>
+ <name>CMSISDAPDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CMSISDAPInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiTargetEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPJtagSpeedList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPRestoreBreakpointsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPUpdateBreakpointsEdit</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>RDICatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchUndef</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchData</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchPrefetch</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchMMERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchNOCPERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchCHKERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSTATERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchBUSERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchINTERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSFERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchHARDERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiCPUEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPMultiCPUNumber</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeCfgOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeConfig</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CMSISDAPProbeConfigRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CMSISDAPSelectedCPUBehaviour</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ICpuName</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCJetEmuParams</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCCMSISDAPUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCCMSISDAPUsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>GDBSERVER_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>TCPIP</name>
+ <state>aaa.bbb.ccc.ddd</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$TOOLKIT_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCJTagBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJTagDoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJTagUpdateBreakpoints</name>
+ <state>main</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>IJET_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>8</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OCIarProbeScriptFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetResetList</name>
+ <version>1</version>
+ <state>10</state>
+ </option>
+ <option>
+ <name>IjetHWResetDuration</name>
+ <state>300</state>
+ </option>
+ <option>
+ <name>IjetHWResetDelay</name>
+ <state>200</state>
+ </option>
+ <option>
+ <name>IjetPowerFromProbe</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetPowerRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>IjetInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiTargetEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetScanChainNonARMDevices</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetIRLength</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetJtagSpeedList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetProtocolRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetSwoPin</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetCpuClockEdit</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IjetSwoPrescalerList</name>
+ <version>1</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetRestoreBreakpointsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetUpdateBreakpointsEdit</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>RDICatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchUndef</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchData</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchPrefetch</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RDICatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>RDICatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CatchMMERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchNOCPERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchCHKERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSTATERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchBUSERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchINTERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchSFERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchHARDERR</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeCfgOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCProbeConfig</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IjetProbeConfigRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiCPUEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetMultiCPUNumber</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetSelectedCPUBehaviour</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ICpuName</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OCJetEmuParams</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetPreferETB</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IjetTraceSettingsList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IjetTraceSizeList</name>
+ <version>0</version>
+ <state>4</state>
+ </option>
+ <option>
+ <name>FlashBoardPathSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCIjetUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCIjetUsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>JLINK_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>16</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>CCCatchSFERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>JLinkSpeed</name>
+ <state>32</state>
+ </option>
+ <option>
+ <name>CCJLinkDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCJLinkHWResetDelay</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>JLinkInitialSpeed</name>
+ <state>32</state>
+ </option>
+ <option>
+ <name>CCDoJlinkMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCScanChainNonARMDevices</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkMultiTarget</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkIRLength</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkCommRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkTCPIP</name>
+ <state>aaa.bbb.ccc.ddd</state>
+ </option>
+ <option>
+ <name>CCJLinkSpeedRadioV2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCUSBDevice</name>
+ <version>1</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCRDICatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchUndef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchData</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchPrefetch</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCRDICatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkBreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkDoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkUpdateBreakpoints</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>CCJLinkInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkResetList</name>
+ <version>6</version>
+ <state>5</state>
+ </option>
+ <option>
+ <name>CCJLinkInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchMMERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchNOCPERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchCHRERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchSTATERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchBUSERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchINTERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchHARDERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCJLinkScriptFile</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCJLinkUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCTcpIpAlt</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCJLinkTcpIpSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCCpuClockEdit</name>
+ <state>72.0</state>
+ </option>
+ <option>
+ <name>CCSwoClockAuto</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSwoClockEdit</name>
+ <state>2000</state>
+ </option>
+ <option>
+ <name>OCJLinkTraceSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCJLinkTraceSourceDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCJLinkDeviceName</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>LMIFTDI_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>2</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>LmiftdiSpeed</name>
+ <state>500</state>
+ </option>
+ <option>
+ <name>CCLmiftdiDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCLmiftdiLogFile</name>
+ <state>$TOOLKIT_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCLmiFtdiInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCLmiFtdiInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>NULINK_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>PEMICRO_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>3</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCJPEMicroShowSettings</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>STLINK_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>7</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCSTLinkInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkResetList</name>
+ <version>3</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCpuClockEdit</name>
+ <state>72.0</state>
+ </option>
+ <option>
+ <name>CCSwoClockAuto</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSwoClockEdit</name>
+ <state>2000</state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCSTLinkDoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkUpdateBreakpoints</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchMMERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchNOCPERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchCHRERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchSTATERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchBUSERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchINTERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchSFERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchHARDERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkCatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkUsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCSTLinkUsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkJtagSpeedList</name>
+ <version>2</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkDAPNumber</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCSTLinkDebugAccessPortRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkUseServerSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSTLinkProbeList</name>
+ <version>1</version>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>THIRDPARTY_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>CThirdPartyDriverDll</name>
+ <state>Browse to your third-party driver</state>
+ </option>
+ <option>
+ <name>CThirdPartyLogFileCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CThirdPartyLogFileEditB</name>
+ <state>$TOOLKIT_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>TIFET_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCMSPFetResetList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetInterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetInterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetTargetVccTypeDefault</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetTargetVoltage</name>
+ <state>###Uninitialized###</state>
+ </option>
+ <option>
+ <name>CCMSPFetVCCDefault</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCMSPFetTargetSettlingtime</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetRadioJtagSpeedType</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCMSPFetConnection</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetUsbComPort</name>
+ <state>Automatic</state>
+ </option>
+ <option>
+ <name>CCMSPFetAllowAccessToBSL</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetDoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCMSPFetLogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCMSPFetRadioEraseFlash</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>XDS100_ID</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>8</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OCDriverInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>TIPackageOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TIPackage</name>
+ <state></state>
+ </option>
+ <option>
+ <name>BoardFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DoLogfile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>LogFile</name>
+ <state>$PROJ_DIR$\cspycomm.log</state>
+ </option>
+ <option>
+ <name>CCXds100BreakpointRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100DoUpdateBreakpoints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100UpdateBreakpoints</name>
+ <state>_call_main</state>
+ </option>
+ <option>
+ <name>CCXds100CatchReset</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchUndef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchSWI</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchData</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchPrefetch</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchIRQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchFIQ</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchCORERESET</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchMMERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchNOCPERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchCHRERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchSTATERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchBUSERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchINTERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchSFERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchHARDERR</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CatchDummy</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100CpuClockEdit</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCXds100SwoClockAuto</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100SwoClockEdit</name>
+ <state>1000</state>
+ </option>
+ <option>
+ <name>CCXds100HWResetDelay</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100ResetList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100UsbSerialNo</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCXds100UsbSerialNoSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100JtagSpeedList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100InterfaceRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100InterfaceCmdLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100ProbeList</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100SWOPortRadio</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXds100SWOPort</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCXDSTargetVccEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCXDSTargetVoltage</name>
+ <state>###Uninitialized###</state>
+ </option>
+ <option>
+ <name>OCXDSDigitalStatesConfigFile</name>
+ <state>1</state>
+ </option>
+ </data>
+ </settings>
+ <debuggerPlugins>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\RemedyRtosViewer\RemedyRtosViewer.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8b.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8bBE.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ <plugin>
+ <file>$EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin</file>
+ <loadFlag>0</loadFlag>
+ </plugin>
+ </debuggerPlugins>
+ </configuration>
+</project>
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewp b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewp
new file mode 100644
index 00000000..20b7d7c3
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewp
@@ -0,0 +1,2137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <fileVersion>3</fileVersion>
+ <configuration>
+ <name>Debug</name>
+ <toolchain>
+ <name>ARM</name>
+ </toolchain>
+ <debug>1</debug>
+ <settings>
+ <name>General</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <version>31</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>ExePath</name>
+ <state>Debug\Exe</state>
+ </option>
+ <option>
+ <name>ObjPath</name>
+ <state>Debug\Obj</state>
+ </option>
+ <option>
+ <name>ListPath</name>
+ <state>Debug\List</state>
+ </option>
+ <option>
+ <name>GEndianMode</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>Input description</name>
+ <state>Full formatting, without multibyte support.</state>
+ </option>
+ <option>
+ <name>Output description</name>
+ <state>Full formatting, without multibyte support.</state>
+ </option>
+ <option>
+ <name>GOutputBinary</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGCoreOrChip</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelect</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelectSlave</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RTDescription</name>
+ <state>Use the normal configuration of the C/C++ runtime library. No locale interface, C locale, no file descriptor support, no multibytes in printf and scanf, and no hex floats in strtod.</state>
+ </option>
+ <option>
+ <name>OGProductVersion</name>
+ <state>5.11.0.50615</state>
+ </option>
+ <option>
+ <name>OGLastSavedByProductVersion</name>
+ <state>8.50.6.28950</state>
+ </option>
+ <option>
+ <name>GeneralEnableMisra</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraVerbose</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGChipSelectEditMenu</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>GenLowLevelInterface</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>GEndianModeBE</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGBufferedTerminalOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenStdoutInterface</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>GeneralMisraVer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>RTConfigPath2</name>
+ <state>$TOOLKIT_DIR$\inc\c\DLib_Config_Normal.h</state>
+ </option>
+ <option>
+ <name>GBECoreSlave</name>
+ <version>28</version>
+ <state>39</state>
+ </option>
+ <option>
+ <name>OGUseCmsis</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGUseCmsisDspLib</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibThreads</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CoreVariant</name>
+ <version>28</version>
+ <state>39</state>
+ </option>
+ <option>
+ <name>GFPUDeviceSlave</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>FPU2</name>
+ <version>0</version>
+ <state>4</state>
+ </option>
+ <option>
+ <name>NrRegs</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>NEON</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GFPUCoreSlave2</name>
+ <version>28</version>
+ <state>39</state>
+ </option>
+ <option>
+ <name>OGCMSISPackSelectDevice</name>
+ </option>
+ <option>
+ <name>OgLibHeap</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGLibAdditionalLocale</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGPrintfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGPrintfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGScanfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGScanfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenLocaleTags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>GenLocaleDisplayOnly</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DSPExtension</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>TrustZone</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TrustZoneModes</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>ICCARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>36</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>CCOptimizationNoSizeConstraints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCPreprocFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocComments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMnemonics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMessages</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagSuppress</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagRemark</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagWarning</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagError</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCAllowList</name>
+ <version>1</version>
+ <state>00000000</state>
+ </option>
+ <option>
+ <name>CCDebugInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IEndianMode</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IExtraOptionsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCLangConformance</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSignedPlainChar</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCRequirePrototypes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagWarnAreErr</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCompilerRuntimeInfo</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OutputFile</name>
+ <state>$FILE_BNAME$.o</state>
+ </option>
+ <option>
+ <name>CCLibConfigHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>PreInclude</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CompilerMisraOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCIncludePath2</name>
+ <state>$PROJ_DIR$\..\inc</state>
+ <state>$PROJ_DIR$\..\..\..\..\common\inc</state>
+ </option>
+ <option>
+ <name>CCStdIncCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCodeSection</name>
+ <state>.text</state>
+ </option>
+ <option>
+ <name>IProcessorMode2</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCOptLevel</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCOptStrategy</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptLevelSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>CCPosIndRopi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndRwpi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndNoDynInit</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccLang</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccCDialect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccAllowVLA</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccStaticDestr</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCppInlineSemantics</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccFloatSemantics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptStrategySlave</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCGuardCalls</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccExceptions2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccRTTI2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OICompilerExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCStackProtection</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>AARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>10</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>AObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AEndian</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>ACaseSensitivity</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacroChars</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnWhat</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnOne</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>ADebug</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AltRegisterNames</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ADefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AList</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AListHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AListing</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>Includes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacDefs</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacExps</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacExec</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OnlyAssed</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MultiLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLengthCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLength</name>
+ <state>80</state>
+ </option>
+ <option>
+ <name>TabSpacing</name>
+ <state>8</state>
+ </option>
+ <option>
+ <name>AXRef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDefines</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefInternal</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDual</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AOutputFile</name>
+ <state>$FILE_BNAME$.o</state>
+ </option>
+ <option>
+ <name>ALimitErrorsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ALimitErrorsEdit</name>
+ <state>100</state>
+ </option>
+ <option>
+ <name>AIgnoreStdInclude</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AUserIncludes</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AExtraOptionsCheckV2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AExtraOptionsV2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AsmNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>OBJCOPY</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OOCOutputFormat</name>
+ <version>3</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCOutputOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OOCOutputFile</name>
+ <state>sample_threadx.srec</state>
+ </option>
+ <option>
+ <name>OOCCommandLineProducer</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OOCObjCopyEnable</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CUSTOM</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <extensions></extensions>
+ <cmdline></cmdline>
+ <hasPrio>0</hasPrio>
+ </data>
+ </settings>
+ <settings>
+ <name>BICOMP</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>BUILDACTION</name>
+ <archiveVersion>1</archiveVersion>
+ <data>
+ <prebuild></prebuild>
+ <postbuild></postbuild>
+ </data>
+ </settings>
+ <settings>
+ <name>ILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>23</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>IlinkLibIOConfig</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>XLinkMisraHandler</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkInputFileSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOutputFile</name>
+ <state>sample_threadx.out</state>
+ </option>
+ <option>
+ <name>IlinkDebugInfoEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkKeepSymbols</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkConfigDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkMapFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogInitialization</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogModule</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogSection</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogVeneer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfOverride</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile</name>
+ <state>$PROJ_DIR$\sample_threadx.icf</state>
+ </option>
+ <option>
+ <name>IlinkIcfFileSlave</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkSuppressDiags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsRem</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsWarn</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsErr</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkWarningsAreErrors</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkUseExtraOptions</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkLowLevelInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAutoLibEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAdditionalLibs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkOverrideProgramEntryLabel</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabelSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabel</name>
+ <state>__iar_program_start</state>
+ </option>
+ <option>
+ <name>DoFill</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>FillerByte</name>
+ <state>0xFF</state>
+ </option>
+ <option>
+ <name>FillerStart</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>FillerEnd</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>CrcSize</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcAlign</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcPoly</name>
+ <state>0x11021</state>
+ </option>
+ <option>
+ <name>CrcCompl</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcBitOrder</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcInitialValue</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>DoCrc</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkBE8Slave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkBufferedTerminalOutput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkStdoutInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcFullSize</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIElfToolPostProcess</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogAutoLibSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogRedirSymbols</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogUnusedFragments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcReverseByteOrder</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcUseAsInput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptInline</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsAllow</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsForce</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptMergeDuplSections</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOptUseVfe</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptForceVfe</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackAnalysisEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackControlFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkStackCallGraphFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CrcAlgorithm</name>
+ <version>1</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcUnitSize</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkThreadsSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLogCallGraph</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile_AltDefault</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkHeapSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLocaleSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkTrustzoneImportLibraryOut</name>
+ <state>sample_threadx_import_lib.o</state>
+ </option>
+ <option>
+ <name>OILinkExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign2</name>
+ <state></state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>IARCHIVE</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>IarchiveInputs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IarchiveOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IarchiveOutput</name>
+ <state>###Unitialized###</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>BILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>Coder</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ </configuration>
+ <configuration>
+ <name>Release</name>
+ <toolchain>
+ <name>ARM</name>
+ </toolchain>
+ <debug>0</debug>
+ <settings>
+ <name>General</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <version>31</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>ExePath</name>
+ <state>Release\Exe</state>
+ </option>
+ <option>
+ <name>ObjPath</name>
+ <state>Release\Obj</state>
+ </option>
+ <option>
+ <name>ListPath</name>
+ <state>Release\List</state>
+ </option>
+ <option>
+ <name>GEndianMode</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>Input description</name>
+ <state></state>
+ </option>
+ <option>
+ <name>Output description</name>
+ <state></state>
+ </option>
+ <option>
+ <name>GOutputBinary</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGCoreOrChip</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelect</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelectSlave</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RTDescription</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OGProductVersion</name>
+ <state>5.11.0.50615</state>
+ </option>
+ <option>
+ <name>OGLastSavedByProductVersion</name>
+ <state>8.11.1.13270</state>
+ </option>
+ <option>
+ <name>GeneralEnableMisra</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraVerbose</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGChipSelectEditMenu</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>GenLowLevelInterface</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GEndianModeBE</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGBufferedTerminalOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenStdoutInterface</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>GeneralMisraVer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>RTConfigPath2</name>
+ <state>dl-stnl0.a</state>
+ </option>
+ <option>
+ <name>GBECoreSlave</name>
+ <version>28</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGUseCmsis</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGUseCmsisDspLib</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibThreads</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CoreVariant</name>
+ <version>28</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GFPUDeviceSlave</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>FPU2</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>NrRegs</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>NEON</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GFPUCoreSlave2</name>
+ <version>28</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGCMSISPackSelectDevice</name>
+ </option>
+ <option>
+ <name>OgLibHeap</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGLibAdditionalLocale</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGPrintfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGPrintfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGScanfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGScanfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenLocaleTags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>GenLocaleDisplayOnly</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DSPExtension</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TrustZone</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TrustZoneModes</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>ICCARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>36</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>CCOptimizationNoSizeConstraints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDefines</name>
+ <state>NDEBUG</state>
+ </option>
+ <option>
+ <name>CCPreprocFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocComments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMnemonics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMessages</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagSuppress</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagRemark</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagWarning</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagError</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCAllowList</name>
+ <version>1</version>
+ <state>11111110</state>
+ </option>
+ <option>
+ <name>CCDebugInfo</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IEndianMode</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IExtraOptionsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCLangConformance</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSignedPlainChar</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCRequirePrototypes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagWarnAreErr</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCompilerRuntimeInfo</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OutputFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCLibConfigHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>PreInclude</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CompilerMisraOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCIncludePath2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCStdIncCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCodeSection</name>
+ <state>.text</state>
+ </option>
+ <option>
+ <name>IProcessorMode2</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCOptLevel</name>
+ <state>3</state>
+ </option>
+ <option>
+ <name>CCOptStrategy</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptLevelSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>CCPosIndRopi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndRwpi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndNoDynInit</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccLang</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccCDialect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccAllowVLA</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccStaticDestr</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCppInlineSemantics</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccFloatSemantics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptStrategySlave</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCGuardCalls</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccExceptions2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccRTTI2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OICompilerExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCStackProtection</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>AARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>10</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>AObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AEndian</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>ACaseSensitivity</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacroChars</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnWhat</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnOne</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>ADebug</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AltRegisterNames</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ADefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AList</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AListHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AListing</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>Includes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacDefs</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacExps</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacExec</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OnlyAssed</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MultiLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLengthCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLength</name>
+ <state>80</state>
+ </option>
+ <option>
+ <name>TabSpacing</name>
+ <state>8</state>
+ </option>
+ <option>
+ <name>AXRef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDefines</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefInternal</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDual</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AOutputFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>ALimitErrorsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ALimitErrorsEdit</name>
+ <state>100</state>
+ </option>
+ <option>
+ <name>AIgnoreStdInclude</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AUserIncludes</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AExtraOptionsCheckV2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AExtraOptionsV2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AsmNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>OBJCOPY</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OOCOutputFormat</name>
+ <version>3</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCOutputOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OOCOutputFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OOCCommandLineProducer</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OOCObjCopyEnable</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CUSTOM</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <extensions></extensions>
+ <cmdline></cmdline>
+ <hasPrio>0</hasPrio>
+ </data>
+ </settings>
+ <settings>
+ <name>BICOMP</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>BUILDACTION</name>
+ <archiveVersion>1</archiveVersion>
+ <data>
+ <prebuild></prebuild>
+ <postbuild></postbuild>
+ </data>
+ </settings>
+ <settings>
+ <name>ILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>23</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>IlinkLibIOConfig</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>XLinkMisraHandler</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkInputFileSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOutputFile</name>
+ <state>###Unitialized###</state>
+ </option>
+ <option>
+ <name>IlinkDebugInfoEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkKeepSymbols</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkConfigDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkMapFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogInitialization</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogModule</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogSection</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogVeneer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile</name>
+ <state>lnk0t.icf</state>
+ </option>
+ <option>
+ <name>IlinkIcfFileSlave</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkSuppressDiags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsRem</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsWarn</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsErr</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkWarningsAreErrors</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkUseExtraOptions</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkLowLevelInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAutoLibEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAdditionalLibs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkOverrideProgramEntryLabel</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabelSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabel</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DoFill</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>FillerByte</name>
+ <state>0xFF</state>
+ </option>
+ <option>
+ <name>FillerStart</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>FillerEnd</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>CrcSize</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcAlign</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcPoly</name>
+ <state>0x11021</state>
+ </option>
+ <option>
+ <name>CrcCompl</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcBitOrder</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcInitialValue</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>DoCrc</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkBE8Slave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkBufferedTerminalOutput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkStdoutInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcFullSize</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIElfToolPostProcess</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogAutoLibSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogRedirSymbols</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogUnusedFragments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcReverseByteOrder</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcUseAsInput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptInline</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsAllow</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsForce</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptMergeDuplSections</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOptUseVfe</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptForceVfe</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackAnalysisEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackControlFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkStackCallGraphFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CrcAlgorithm</name>
+ <version>1</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcUnitSize</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkThreadsSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLogCallGraph</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile_AltDefault</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkHeapSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLocaleSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkTrustzoneImportLibraryOut</name>
+ <state>###Unitialized###</state>
+ </option>
+ <option>
+ <name>OILinkExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign2</name>
+ <state></state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>IARCHIVE</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>IarchiveInputs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IarchiveOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IarchiveOutput</name>
+ <state>###Unitialized###</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>BILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>Coder</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ </configuration>
+ <file>
+ <name>$PROJ_DIR$\cstartup_M.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\sample_threadx.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\Debug\Exe\tx.a</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\tx_initialize_low_level.s</name>
+ </file>
+</project>
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.icf b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.icf
new file mode 100644
index 00000000..246d387e
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.icf
@@ -0,0 +1,42 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x00000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x0007FFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x200;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+define symbol FlashConfig_start__= 0x00000400;
+define symbol FlashConfig_end__ = 0x0000040f;
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to (FlashConfig_start__ - 1)] | [from (FlashConfig_end__+1) to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+define region FlashConfig_region = mem:[from FlashConfig_start__ to FlashConfig_end__];
+
+initialize by copy { readwrite };
+initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
+
+place in FlashConfig_region
+ {section FlashConfig};
+
+place in RAM_region { last section FREE_MEM};
+
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp b/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp
new file mode 100644
index 00000000..cccb9a9a
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp
@@ -0,0 +1,2752 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <fileVersion>3</fileVersion>
+ <configuration>
+ <name>Debug</name>
+ <toolchain>
+ <name>ARM</name>
+ </toolchain>
+ <debug>1</debug>
+ <settings>
+ <name>General</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <version>31</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>ExePath</name>
+ <state>Debug\Exe</state>
+ </option>
+ <option>
+ <name>ObjPath</name>
+ <state>Debug\Obj</state>
+ </option>
+ <option>
+ <name>ListPath</name>
+ <state>Debug\List</state>
+ </option>
+ <option>
+ <name>GEndianMode</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>Input description</name>
+ <state>Full formatting, without multibyte support.</state>
+ </option>
+ <option>
+ <name>Output description</name>
+ <state>Full formatting, without multibyte support.</state>
+ </option>
+ <option>
+ <name>GOutputBinary</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGCoreOrChip</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelect</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelectSlave</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RTDescription</name>
+ <state>To be used with the normal configuration of the C/C++ runtime library. No locale interface, C locale, no file descriptor support, no multibytes in printf and scanf, and no hex floats in strtod.</state>
+ </option>
+ <option>
+ <name>OGProductVersion</name>
+ <state>5.11.0.50615</state>
+ </option>
+ <option>
+ <name>OGLastSavedByProductVersion</name>
+ <state>8.50.6.28950</state>
+ </option>
+ <option>
+ <name>GeneralEnableMisra</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraVerbose</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGChipSelectEditMenu</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>GenLowLevelInterface</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>GEndianModeBE</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGBufferedTerminalOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenStdoutInterface</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>GeneralMisraVer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>RTConfigPath2</name>
+ <state>$TOOLKIT_DIR$\inc\c\DLib_Config_Normal.h</state>
+ </option>
+ <option>
+ <name>GBECoreSlave</name>
+ <version>28</version>
+ <state>39</state>
+ </option>
+ <option>
+ <name>OGUseCmsis</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGUseCmsisDspLib</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibThreads</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CoreVariant</name>
+ <version>28</version>
+ <state>39</state>
+ </option>
+ <option>
+ <name>GFPUDeviceSlave</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>FPU2</name>
+ <version>0</version>
+ <state>4</state>
+ </option>
+ <option>
+ <name>NrRegs</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>NEON</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GFPUCoreSlave2</name>
+ <version>28</version>
+ <state>39</state>
+ </option>
+ <option>
+ <name>OGCMSISPackSelectDevice</name>
+ </option>
+ <option>
+ <name>OgLibHeap</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGLibAdditionalLocale</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGPrintfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGPrintfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGScanfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGScanfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenLocaleTags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>GenLocaleDisplayOnly</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DSPExtension</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>TrustZone</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TrustZoneModes</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>ICCARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>36</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>CCOptimizationNoSizeConstraints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCPreprocFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocComments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMnemonics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMessages</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagSuppress</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagRemark</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagWarning</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagError</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCAllowList</name>
+ <version>1</version>
+ <state>00000000</state>
+ </option>
+ <option>
+ <name>CCDebugInfo</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IEndianMode</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IExtraOptionsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCLangConformance</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSignedPlainChar</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCRequirePrototypes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagWarnAreErr</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCompilerRuntimeInfo</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OutputFile</name>
+ <state>$FILE_BNAME$.o</state>
+ </option>
+ <option>
+ <name>CCLibConfigHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>PreInclude</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CompilerMisraOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCIncludePath2</name>
+ <state>$PROJ_DIR$\..\inc</state>
+ <state>$PROJ_DIR$\..\..\..\..\common\inc</state>
+ </option>
+ <option>
+ <name>CCStdIncCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCodeSection</name>
+ <state>.text</state>
+ </option>
+ <option>
+ <name>IProcessorMode2</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCOptLevel</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCOptStrategy</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptLevelSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>CCPosIndRopi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndRwpi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndNoDynInit</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccLang</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccCDialect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccAllowVLA</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccStaticDestr</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCppInlineSemantics</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccFloatSemantics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptStrategySlave</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCGuardCalls</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccExceptions2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccRTTI2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OICompilerExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCStackProtection</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>AARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>10</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>AObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AEndian</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>ACaseSensitivity</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacroChars</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnWhat</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnOne</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>ADebug</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AltRegisterNames</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ADefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AList</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AListHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AListing</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>Includes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacDefs</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacExps</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacExec</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OnlyAssed</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MultiLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLengthCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLength</name>
+ <state>80</state>
+ </option>
+ <option>
+ <name>TabSpacing</name>
+ <state>8</state>
+ </option>
+ <option>
+ <name>AXRef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDefines</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefInternal</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDual</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AOutputFile</name>
+ <state>$FILE_BNAME$.o</state>
+ </option>
+ <option>
+ <name>ALimitErrorsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ALimitErrorsEdit</name>
+ <state>100</state>
+ </option>
+ <option>
+ <name>AIgnoreStdInclude</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AUserIncludes</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AExtraOptionsCheckV2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AExtraOptionsV2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AsmNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>OBJCOPY</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>OOCOutputFormat</name>
+ <version>3</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCOutputOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OOCOutputFile</name>
+ <state>tx.srec</state>
+ </option>
+ <option>
+ <name>OOCCommandLineProducer</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OOCObjCopyEnable</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CUSTOM</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <extensions></extensions>
+ <cmdline></cmdline>
+ <hasPrio>0</hasPrio>
+ </data>
+ </settings>
+ <settings>
+ <name>BICOMP</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>BUILDACTION</name>
+ <archiveVersion>1</archiveVersion>
+ <data>
+ <prebuild></prebuild>
+ <postbuild></postbuild>
+ </data>
+ </settings>
+ <settings>
+ <name>ILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>23</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>IlinkLibIOConfig</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>XLinkMisraHandler</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkInputFileSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOutputFile</name>
+ <state>tx.out</state>
+ </option>
+ <option>
+ <name>IlinkDebugInfoEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkKeepSymbols</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkConfigDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkMapFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogInitialization</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogModule</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogSection</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogVeneer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile</name>
+ <state>lnk0t.icf</state>
+ </option>
+ <option>
+ <name>IlinkIcfFileSlave</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkSuppressDiags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsRem</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsWarn</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsErr</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkWarningsAreErrors</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkUseExtraOptions</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkLowLevelInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAutoLibEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAdditionalLibs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkOverrideProgramEntryLabel</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabelSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabel</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DoFill</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>FillerByte</name>
+ <state>0xFF</state>
+ </option>
+ <option>
+ <name>FillerStart</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>FillerEnd</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>CrcSize</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcAlign</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcPoly</name>
+ <state>0x11021</state>
+ </option>
+ <option>
+ <name>CrcCompl</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcBitOrder</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcInitialValue</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>DoCrc</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkBE8Slave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkBufferedTerminalOutput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkStdoutInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcFullSize</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIElfToolPostProcess</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogAutoLibSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogRedirSymbols</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogUnusedFragments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcReverseByteOrder</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcUseAsInput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptInline</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsAllow</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsForce</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptMergeDuplSections</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOptUseVfe</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptForceVfe</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackAnalysisEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackControlFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkStackCallGraphFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CrcAlgorithm</name>
+ <version>1</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcUnitSize</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkThreadsSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLogCallGraph</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile_AltDefault</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkHeapSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLocaleSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkTrustzoneImportLibraryOut</name>
+ <state>###Unitialized###</state>
+ </option>
+ <option>
+ <name>OILinkExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign2</name>
+ <state></state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>IARCHIVE</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>1</debug>
+ <option>
+ <name>IarchiveInputs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IarchiveOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IarchiveOutput</name>
+ <state>C:\Users\sclarson\repos\tx_m\ports\armv7-m\iar\sample_cortex_m4\Debug\Exe\tx.a</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>BILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>Coder</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ </configuration>
+ <configuration>
+ <name>Release</name>
+ <toolchain>
+ <name>ARM</name>
+ </toolchain>
+ <debug>0</debug>
+ <settings>
+ <name>General</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <version>31</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>ExePath</name>
+ <state>Release\Exe</state>
+ </option>
+ <option>
+ <name>ObjPath</name>
+ <state>Release\Obj</state>
+ </option>
+ <option>
+ <name>ListPath</name>
+ <state>Release\List</state>
+ </option>
+ <option>
+ <name>GEndianMode</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>Input description</name>
+ <state></state>
+ </option>
+ <option>
+ <name>Output description</name>
+ <state></state>
+ </option>
+ <option>
+ <name>GOutputBinary</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGCoreOrChip</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelect</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>GRuntimeLibSelectSlave</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>RTDescription</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OGProductVersion</name>
+ <state>5.11.0.50615</state>
+ </option>
+ <option>
+ <name>OGLastSavedByProductVersion</name>
+ <state>8.11.1.13270</state>
+ </option>
+ <option>
+ <name>GeneralEnableMisra</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraVerbose</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGChipSelectEditMenu</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>GenLowLevelInterface</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GEndianModeBE</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGBufferedTerminalOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenStdoutInterface</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>GeneralMisraVer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GeneralMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>RTConfigPath2</name>
+ <state>dl-stnl0.a</state>
+ </option>
+ <option>
+ <name>GBECoreSlave</name>
+ <version>28</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGUseCmsis</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGUseCmsisDspLib</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GRuntimeLibThreads</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CoreVariant</name>
+ <version>28</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GFPUDeviceSlave</name>
+ <state>Default None</state>
+ </option>
+ <option>
+ <name>FPU2</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>NrRegs</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>NEON</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GFPUCoreSlave2</name>
+ <version>28</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGCMSISPackSelectDevice</name>
+ </option>
+ <option>
+ <name>OgLibHeap</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGLibAdditionalLocale</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGPrintfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGPrintfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OGScanfVariant</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OGScanfMultibyteSupport</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>GenLocaleTags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>GenLocaleDisplayOnly</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DSPExtension</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TrustZone</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>TrustZoneModes</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>ICCARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>36</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>CCOptimizationNoSizeConstraints</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDefines</name>
+ <state>NDEBUG</state>
+ </option>
+ <option>
+ <name>CCPreprocFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocComments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPreprocLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMnemonics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListCMessages</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCListAssSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagSuppress</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagRemark</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagWarning</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCDiagError</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCAllowList</name>
+ <version>1</version>
+ <state>11111110</state>
+ </option>
+ <option>
+ <name>CCDebugInfo</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IEndianMode</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IExtraOptionsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCLangConformance</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCSignedPlainChar</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCRequirePrototypes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCDiagWarnAreErr</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCompilerRuntimeInfo</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OutputFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCLibConfigHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>PreInclude</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CompilerMisraOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCIncludePath2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CCStdIncCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCCodeSection</name>
+ <state>.text</state>
+ </option>
+ <option>
+ <name>IProcessorMode2</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCOptLevel</name>
+ <state>3</state>
+ </option>
+ <option>
+ <name>CCOptStrategy</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptLevelSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules98</name>
+ <version>0</version>
+ <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>
+ </option>
+ <option>
+ <name>CompilerMisraRules04</name>
+ <version>0</version>
+ <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state>
+ </option>
+ <option>
+ <name>CCPosIndRopi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndRwpi</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCPosIndNoDynInit</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccLang</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccCDialect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccAllowVLA</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccStaticDestr</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCppInlineSemantics</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IccFloatSemantics</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCOptStrategySlave</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCGuardCalls</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncSource</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CCEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccExceptions2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IccRTTI2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OICompilerExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CCStackProtection</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>AARM</name>
+ <archiveVersion>2</archiveVersion>
+ <data>
+ <version>10</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>AObjPrefix</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AEndian</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>ACaseSensitivity</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacroChars</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnWhat</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AWarnOne</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange1</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AWarnRange2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>ADebug</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AltRegisterNames</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ADefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AList</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AListHeader</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AListing</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>Includes</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacDefs</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MacExps</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>MacExec</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OnlyAssed</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>MultiLine</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLengthCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>PageLength</name>
+ <state>80</state>
+ </option>
+ <option>
+ <name>TabSpacing</name>
+ <state>8</state>
+ </option>
+ <option>
+ <name>AXRef</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDefines</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefInternal</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AXRefDual</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AFpuProcessor</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>AOutputFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>ALimitErrorsCheck</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>ALimitErrorsEdit</name>
+ <state>100</state>
+ </option>
+ <option>
+ <name>AIgnoreStdInclude</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AUserIncludes</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AExtraOptionsCheckV2</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>AExtraOptionsV2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>AsmNoLiteralPool</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>OBJCOPY</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>1</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>OOCOutputFormat</name>
+ <version>3</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OCOutputOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>OOCOutputFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>OOCCommandLineProducer</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>OOCObjCopyEnable</name>
+ <state>0</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>CUSTOM</name>
+ <archiveVersion>3</archiveVersion>
+ <data>
+ <extensions></extensions>
+ <cmdline></cmdline>
+ <hasPrio>0</hasPrio>
+ </data>
+ </settings>
+ <settings>
+ <name>BICOMP</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>BUILDACTION</name>
+ <archiveVersion>1</archiveVersion>
+ <data>
+ <prebuild></prebuild>
+ <postbuild></postbuild>
+ </data>
+ </settings>
+ <settings>
+ <name>ILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>23</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>IlinkLibIOConfig</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>XLinkMisraHandler</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkInputFileSlave</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOutputFile</name>
+ <state>###Unitialized###</state>
+ </option>
+ <option>
+ <name>IlinkDebugInfoEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkKeepSymbols</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkConfigDefines</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkMapFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogFile</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogInitialization</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogModule</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogSection</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogVeneer</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile</name>
+ <state>lnk0t.icf</state>
+ </option>
+ <option>
+ <name>IlinkIcfFileSlave</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEnableRemarks</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkSuppressDiags</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsRem</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsWarn</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkTreatAsErr</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkWarningsAreErrors</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkUseExtraOptions</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkExtraOptions</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkLowLevelInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAutoLibEnable</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkAdditionalLibs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkOverrideProgramEntryLabel</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabelSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkProgramEntryLabel</name>
+ <state></state>
+ </option>
+ <option>
+ <name>DoFill</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>FillerByte</name>
+ <state>0xFF</state>
+ </option>
+ <option>
+ <name>FillerStart</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>FillerEnd</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>CrcSize</name>
+ <version>0</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcAlign</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcPoly</name>
+ <state>0x11021</state>
+ </option>
+ <option>
+ <name>CrcCompl</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcBitOrder</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>CrcInitialValue</name>
+ <state>0x0</state>
+ </option>
+ <option>
+ <name>DoCrc</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkBE8Slave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkBufferedTerminalOutput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkStdoutInterfaceSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcFullSize</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIElfToolPostProcess</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogAutoLibSelect</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogRedirSymbols</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkLogUnusedFragments</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcReverseByteOrder</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCrcUseAsInput</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptInline</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsAllow</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptExceptionsForce</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkCmsis</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptMergeDuplSections</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkOptUseVfe</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkOptForceVfe</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackAnalysisEnable</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkStackControlFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkStackCallGraphFile</name>
+ <state></state>
+ </option>
+ <option>
+ <name>CrcAlgorithm</name>
+ <version>1</version>
+ <state>1</state>
+ </option>
+ <option>
+ <name>CrcUnitSize</name>
+ <version>0</version>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkThreadsSlave</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLogCallGraph</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkIcfFile_AltDefault</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkEncInput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutput</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IlinkEncOutputBom</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkHeapSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkLocaleSelect</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkTrustzoneImportLibraryOut</name>
+ <state>###Unitialized###</state>
+ </option>
+ <option>
+ <name>OILinkExtraOption</name>
+ <state>1</state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryFile2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySymbol2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinarySegment2</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IlinkRawBinaryAlign2</name>
+ <state></state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>IARCHIVE</name>
+ <archiveVersion>0</archiveVersion>
+ <data>
+ <version>0</version>
+ <wantNonLocal>1</wantNonLocal>
+ <debug>0</debug>
+ <option>
+ <name>IarchiveInputs</name>
+ <state></state>
+ </option>
+ <option>
+ <name>IarchiveOverride</name>
+ <state>0</state>
+ </option>
+ <option>
+ <name>IarchiveOutput</name>
+ <state>###Unitialized###</state>
+ </option>
+ </data>
+ </settings>
+ <settings>
+ <name>BILINK</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ <settings>
+ <name>Coder</name>
+ <archiveVersion>0</archiveVersion>
+ <data />
+ </settings>
+ </configuration>
+ <group>
+ <name>inc</name>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_api.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_block_pool.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_byte_pool.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_event_flags.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_initialize.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_mutex.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\inc\tx_port.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_queue.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_semaphore.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_thread.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_timer.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_trace.h</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\inc\tx_user.h</name>
+ </file>
+ </group>
+ <group>
+ <name>src</name>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_allocate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_cleanup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_pool_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_block_release.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_allocate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_cleanup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_pool_search.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_byte_release.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_cleanup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_set.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_event_flags_set_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_iar.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_initialize_high_level.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_initialize_kernel_enter.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_initialize_kernel_setup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_cleanup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_priority_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_mutex_put.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_cleanup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_flush.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_front_send.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_receive.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_send.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_queue_send_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_ceiling_put.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_cleanup.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_put.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_semaphore_put_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_context_restore.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_context_save.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_entry_exit_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_identify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_interrupt_control.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_interrupt_disable.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_interrupt_restore.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_preemption_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_priority_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_relinquish.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_reset.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_resume.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_schedule.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_shell_entry.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_sleep.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_stack_analyze.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_stack_build.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_stack_error_handler.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_stack_error_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_suspend.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_system_preempt_check.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_system_resume.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_thread_system_return.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_system_suspend.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_terminate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_time_slice.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_time_slice_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_timeout.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_thread_wait_abort.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_time_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_time_set.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_activate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_deactivate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_expiration_process.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\src\tx_timer_interrupt.s</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_performance_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_performance_system_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_system_activate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_system_deactivate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_timer_thread_entry.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_buffer_full_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_disable.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_enable.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_event_filter.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_event_unfilter.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_initialize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_interrupt_control.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_isr_enter_insert.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_isr_exit_insert.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_object_register.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_object_unregister.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\tx_trace_user_event_insert.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_block_allocate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_block_pool_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_block_pool_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_block_pool_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_block_pool_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_block_release.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_byte_allocate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_byte_pool_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_byte_pool_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_byte_pool_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_byte_pool_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_byte_release.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_event_flags_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_event_flags_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_event_flags_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_event_flags_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_event_flags_set.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_event_flags_set_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_mutex_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_mutex_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_mutex_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_mutex_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_mutex_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_mutex_put.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_flush.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_front_send.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_receive.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_send.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_queue_send_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_ceiling_put.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_prioritize.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_put.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_semaphore_put_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_entry_exit_notify.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_info_get.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_preemption_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_priority_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_relinquish.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_reset.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_resume.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_suspend.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_terminate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_time_slice_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_thread_wait_abort.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_timer_activate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_timer_change.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_timer_create.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_timer_deactivate.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_timer_delete.c</name>
+ </file>
+ <file>
+ <name>$PROJ_DIR$\..\..\..\..\common\src\txe_timer_info_get.c</name>
+ </file>
+ </group>
+</project>
diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s
new file mode 100644
index 00000000..d7d3fd9e
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s
@@ -0,0 +1,151 @@
+/**************************************************************************/
+/* */
+/* 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_thread_system_stack_ptr
+ EXTERN _tx_initialize_unused_memory
+ EXTERN _tx_timer_interrupt
+ EXTERN __vector_table
+ EXTERN _tx_execution_isr_enter
+ EXTERN _tx_execution_isr_exit
+
+SYSTEM_CLOCK EQU 25000000
+SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 100) -1)
+
+ RSEG FREE_MEM:DATA
+ PUBLIC __tx_free_memory_start
+__tx_free_memory_start
+ DS32 4
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mx/IAR */
+/* 6.1.10 */
+/* 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ PUBLIC _tx_initialize_low_level
+_tx_initialize_low_level:
+
+ /* Ensure that interrupts are disabled. */
+ CPSID i
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =__tx_free_memory_start // Get end of non-initialized RAM area
+ LDR r2, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ STR r0, [r2, #0] // Save first free memory address
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =__vector_table // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =__vector_table // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+#ifndef TX_NO_TIMER
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+#endif
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+#ifndef TX_NO_TIMER
+ PUBLIC SysTick_Handler
+ PUBLIC __tx_SysTickHandler
+__tx_SysTickHandler:
+SysTick_Handler:
+// VOID SysTick_Handler(VOID)
+// {
+
+ PUSH {r0, lr}
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0, lr}
+ BX lr
+// }
+#endif
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/readme_threadx.txt b/ports_arch/ARMv7-M/threadx/iar/readme_threadx.txt
new file mode 100644
index 00000000..28b54e03
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/readme_threadx.txt
@@ -0,0 +1,215 @@
+ Microsoft's Azure RTOS ThreadX for ARMv7-M
+ (Cortex-M3, Cortex-M4, Cortex-M7)
+ Using IAR EWARM Tools
+
+
+1. Building the ThreadX run-time Library
+
+Building the ThreadX library is easy. First, open the Azure RTOS workspace
+azure_rtos.eww. Next, make the TX project the "active project" in the
+IAR Embedded Workbench and select the "Make" button. You should observe
+assembly and compilation of a series of ThreadX source files. This
+results in the ThreadX run-time library file tx.a, which is needed by
+the application.
+
+
+2. Demonstration System
+
+The ThreadX demonstration is designed to execute under the IAR debugger under
+simulation.
+
+Building the demonstration is easy; simply open the threadx.www workspace file,
+make the sample_threadx.ewp project the "active project" in the IAR Embedded
+Workbench, and select the "Make" button.
+
+You should observe the compilation of sample_threadx.c (which is the demonstration
+application) and linking with tx.a. The resulting file sample_threadx.out is a
+binary ELF file that can be downloaded and executed on the IAR Windows-based
+Cortex-M simulator.
+
+
+3. System Initialization
+
+The entry point in ThreadX for the Cortex-M using IAR tools is at label
+__iar_program_start. This is defined within the IAR compiler's startup code.
+In addition, this is where all static and global preset C variable
+initialization processing takes place.
+
+The ThreadX tx_initialize_low_level.s file is responsible for setting up
+various system data structures, and a periodic timer interrupt source.
+By default, the vector area is defined at the top of cstartup_M.s, which is
+a slightly modified from the base IAR file.
+
+The _tx_initialize_low_level function inside of tx_initialize_low_level.s
+also 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. To accomplish this, a section is created in
+tx_initialize_low_level.s called FREE_MEM, which must be located after all
+other RAM sections in memory.
+
+
+4. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-M version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 lr Interrupted lr (lr at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+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 it run faster, you can change the ThreadX library
+project to enable various compiler 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.
+
+
+6. Interrupt Handling
+
+The Cortex-M vectors start at the label __vector_table and is defined in cstartup_M.s.
+The application may modify the vector area according to its needs.
+
+
+6.1 Managed Interrupts
+
+ISRs for Cortex-M using the IAR tools can be written completely in C (or assembly
+language) without any calls to _tx_thread_context_save or _tx_thread_context_restore.
+These ISRs are allowed access to the ThreadX API that is available to ISRs.
+
+ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
+
+void your_C_isr(void)
+{
+
+ /* ISR processing goes here, including any needed function calls. */
+}
+
+ISRs written in assembly language will take the form:
+
+ PUBLIC your_assembly_isr
+your_assembly_isr:
+
+ PUSH {r0, lr}
+
+ ; ISR processing goes here, including any needed function calls.
+
+ POP {r0, lr}
+ BX lr
+
+
+7. IAR Thread-safe Library Support
+
+Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
+and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
+should have the following line added (if not already in place):
+
+initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
+
+The project options "General Options -> Library Configuration" should also have the
+"Enable thread support in library" box selected.
+
+
+8. VFP Support
+
+ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context - no additional setup by the application.
+
+
+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:
+
+06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using IAR's ARM tools.
+
+
+Copyright(c) 1996-2021 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c b/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c
new file mode 100644
index 00000000..dd719370
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c
@@ -0,0 +1,804 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** IAR Multithreaded Library Support */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Define IAR library for tools prior to version 8. */
+
+#if (__VER__ < 8000000)
+
+
+/* IAR version 7 and below. */
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/* This implementation requires that the following macros are defined in the
+ tx_port.h file and <yvals.h> is included with the following code segments:
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+ This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
+ application.
+
+ Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
+*/
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+
+#include <yvals.h>
+
+
+#if _MULTI_THREAD
+
+TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
+UINT __tx_iar_system_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_system_lock_no_mutexes;
+UINT __tx_iar_system_lock_internal_errors;
+UINT __tx_iar_system_lock_isr_caller;
+
+
+/* Define the TLS access function for the IAR library. */
+
+void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
+{
+
+char _DLIB_TLS_MEMORY *p = 0;
+
+ /* Is there a current thread? */
+ if (_tx_thread_current_ptr)
+ p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
+ else
+ p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
+ p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
+ return (void _DLIB_TLS_MEMORY *) p;
+}
+
+
+/* Define mutexes for IAR library. */
+
+void __iar_system_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_LOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_system_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_system_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_system_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+}
+
+
+#if _DLIB_FILE_DESCRIPTOR
+
+TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
+UINT __tx_iar_file_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_file_lock_no_mutexes;
+UINT __tx_iar_file_lock_internal_errors;
+UINT __tx_iar_file_lock_isr_caller;
+
+
+void __iar_file_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_FLOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_file_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_file_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_file_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+#endif /* _DLIB_FILE_DESCRIPTOR */
+
+#endif /* _MULTI_THREAD */
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#else /* IAR version 8 and above. */
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+/* This implementation requires that the following macros are defined in the
+ tx_port.h file and <yvals.h> is included with the following code segments:
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+void *_tx_iar_create_per_thread_tls_area(void);
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+void __iar_Initlocks(void);
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+ This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
+ application.
+
+ Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
+*/
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+
+#include <DLib_threads.h>
+
+
+void * __aeabi_read_tp();
+
+void* _tx_iar_create_per_thread_tls_area();
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+
+#pragma section="__iar_tls$$DATA"
+
+/* Define the TLS access function for the IAR library. */
+void * __aeabi_read_tp(void)
+{
+ void *p = 0;
+ TX_THREAD *thread_ptr = _tx_thread_current_ptr;
+ if (thread_ptr)
+ {
+ p = thread_ptr->tx_thread_iar_tls_pointer;
+ }
+ else
+ {
+ p = __section_begin("__iar_tls$$DATA");
+ }
+ return p;
+}
+
+/* Define the TLS creation and destruction to use malloc/free. */
+
+void* _tx_iar_create_per_thread_tls_area()
+{
+ UINT tls_size = __iar_tls_size();
+
+ /* Get memory for TLS. */
+ void *p = malloc(tls_size);
+
+ /* Initialize TLS-area and run constructors for objects in TLS */
+ __iar_tls_init(p);
+ return p;
+}
+
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
+{
+ /* Destroy objects living in TLS */
+ __call_thread_dtors();
+ free(tls_ptr);
+}
+
+#ifndef _MAX_LOCK
+#define _MAX_LOCK 4
+#endif
+
+static TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
+static UINT __tx_iar_system_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_system_lock_no_mutexes;
+UINT __tx_iar_system_lock_internal_errors;
+UINT __tx_iar_system_lock_isr_caller;
+
+
+/* Define mutexes for IAR library. */
+
+void __iar_system_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_LOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_system_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_system_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_system_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *m)
+{
+ if (*m)
+ {
+ UINT status;
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+ }
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *m)
+{
+ if (*m)
+ {
+ UINT status;
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+ }
+}
+
+
+#if _DLIB_FILE_DESCRIPTOR
+
+#include <stdio.h> /* Added to get access to FOPEN_MAX */
+#ifndef _MAX_FLOCK
+#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */
+#endif
+
+
+TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
+UINT __tx_iar_file_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_file_lock_no_mutexes;
+UINT __tx_iar_file_lock_internal_errors;
+UINT __tx_iar_file_lock_isr_caller;
+
+
+void __iar_file_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_FLOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_file_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_file_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_file_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+#endif /* _DLIB_FILE_DESCRIPTOR */
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#endif /* IAR version 8 and above. */
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_misra.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_misra.s
new file mode 100644
index 00000000..ab3fef69
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_misra.s
@@ -0,0 +1,763 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ #define SHT_PROGBITS 0x1
+
+ EXTERN __aeabi_memset
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_interrupt_disable
+ EXTERN _tx_thread_interrupt_restore
+ EXTERN _tx_thread_stack_analyze
+ EXTERN _tx_thread_stack_error_handler
+ EXTERN _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ EXTERN _tx_trace_buffer_current_ptr
+ EXTERN _tx_trace_buffer_end_ptr
+ EXTERN _tx_trace_buffer_start_ptr
+ EXTERN _tx_trace_event_enable_bits
+ EXTERN _tx_trace_full_notify_function
+ EXTERN _tx_trace_header_ptr
+#endif
+
+ PUBLIC _tx_misra_always_true
+ PUBLIC _tx_misra_block_pool_to_uchar_pointer_convert
+ PUBLIC _tx_misra_byte_pool_to_uchar_pointer_convert
+ PUBLIC _tx_misra_char_to_uchar_pointer_convert
+ PUBLIC _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ PUBLIC _tx_misra_indirect_void_to_uchar_pointer_convert
+ PUBLIC _tx_misra_memset
+ PUBLIC _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_object_to_uchar_pointer_convert
+#endif
+ PUBLIC _tx_misra_pointer_to_ulong_convert
+ PUBLIC _tx_misra_status_get
+ PUBLIC _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_time_stamp_get
+#endif
+ PUBLIC _tx_misra_timer_indirect_to_void_pointer_convert
+ PUBLIC _tx_misra_timer_pointer_add
+ PUBLIC _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_trace_event_insert
+#endif
+ PUBLIC _tx_misra_uchar_pointer_add
+ PUBLIC _tx_misra_uchar_pointer_dif
+ PUBLIC _tx_misra_uchar_pointer_sub
+ PUBLIC _tx_misra_uchar_to_align_type_pointer_convert
+ PUBLIC _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_uchar_to_entry_pointer_convert
+ PUBLIC _tx_misra_uchar_to_header_pointer_convert
+#endif
+ PUBLIC _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ PUBLIC _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_uchar_to_object_pointer_convert
+#endif
+ PUBLIC _tx_misra_uchar_to_void_pointer_convert
+ PUBLIC _tx_misra_ulong_pointer_add
+ PUBLIC _tx_misra_ulong_pointer_dif
+ PUBLIC _tx_misra_ulong_pointer_sub
+ PUBLIC _tx_misra_ulong_to_pointer_convert
+ PUBLIC _tx_misra_ulong_to_thread_pointer_convert
+ PUBLIC _tx_misra_user_timer_pointer_get
+ PUBLIC _tx_misra_void_to_block_pool_pointer_convert
+ PUBLIC _tx_misra_void_to_byte_pool_pointer_convert
+ PUBLIC _tx_misra_void_to_event_flags_pointer_convert
+ PUBLIC _tx_misra_void_to_indirect_uchar_pointer_convert
+ PUBLIC _tx_misra_void_to_mutex_pointer_convert
+ PUBLIC _tx_misra_void_to_queue_pointer_convert
+ PUBLIC _tx_misra_void_to_semaphore_pointer_convert
+ PUBLIC _tx_misra_void_to_thread_pointer_convert
+ PUBLIC _tx_misra_void_to_uchar_pointer_convert
+ PUBLIC _tx_misra_void_to_ulong_pointer_convert
+ PUBLIC _tx_misra_ipsr_get
+ PUBLIC _tx_misra_control_get
+ PUBLIC _tx_misra_control_set
+#ifdef __ARMVFP__
+ PUBLIC _tx_misra_fpccr_get
+ PUBLIC _tx_misra_vfp_touch
+#endif
+
+ PUBLIC _tx_misra_event_flags_group_not_used
+ PUBLIC _tx_misra_event_flags_set_notify_not_used
+ PUBLIC _tx_misra_queue_not_used
+ PUBLIC _tx_misra_queue_send_notify_not_used
+ PUBLIC _tx_misra_semaphore_not_used
+ PUBLIC _tx_misra_semaphore_put_notify_not_used
+ PUBLIC _tx_misra_thread_entry_exit_notify_not_used
+ PUBLIC _tx_misra_thread_not_used
+
+#ifdef TX_MISRA_ENABLE
+ PUBLIC _tx_version_id
+
+ SECTION `.data`:DATA:REORDER:NOROOT(2)
+ DATA
+// 51 CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.1 MISRA C Compliant *";
+_tx_version_id:
+ DC8 43H, 6FH, 70H, 79H, 72H, 69H, 67H, 68H
+ DC8 74H, 20H, 28H, 63H, 29H, 20H, 31H, 39H
+ DC8 39H, 36H, 2DH, 32H, 30H, 31H, 38H, 20H
+ DC8 45H, 78H, 70H, 72H, 65H, 73H, 73H, 20H
+ DC8 4CH, 6FH, 67H, 69H, 63H, 20H, 49H, 6EH
+ DC8 63H, 2EH, 20H, 2AH, 20H, 54H, 68H, 72H
+ DC8 65H, 61H, 64H, 58H, 20H, 36H, 2EH, 31H
+ DC8 20H, 4DH, 49H, 53H, 52H, 41H, 20H, 43H
+ DC8 20H, 43H, 6FH, 6DH, 70H, 6CH, 69H, 61H
+ DC8 6EH, 74H, 20H, 2AH, 0
+ DC8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+#endif //TX_MISRA_ENABLE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N ??_tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N ??_tx_misra_message_copy_1
+??_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+??_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N ??_tx_misra_message_copy_2
+??_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N ??_tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR.N R2,??DataTable2 // 0x54485244
+ CMP R1,R2
+ BNE.N ??_tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N ??_tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+??_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N ??_tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N ??_tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N ??_tx_misra_thread_stack_check_3
+??_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+??_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N ??_tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+??_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,??DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R5,??DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R5,??DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,??DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N ??_tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N ??_tx_misra_trace_event_insert_2
+??_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N ??_tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N ??_tx_misra_trace_event_insert_2
+??_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+??_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,??DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N ??_tx_misra_trace_event_insert_4
+ LDR.N R0,??DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,??DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,??DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N ??_tx_misra_trace_event_insert_0
+??_tx_misra_trace_event_insert_4:
+ LDR.N R0,??DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+??_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_1:
+ DC32 _tx_trace_buffer_current_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_2:
+ DC32 _tx_trace_event_enable_bits
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_5:
+ DC32 _tx_trace_buffer_end_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_6:
+ DC32 _tx_trace_buffer_start_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_7:
+ DC32 _tx_trace_header_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_8:
+ DC32 _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2:
+ DC32 0x54485244
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_3:
+ DC32 _tx_thread_system_state
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_4:
+ DC32 _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARMVFP__
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+ DC32 0
+
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_restore.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_restore.s
new file mode 100644
index 00000000..eaa2f9ef
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_restore.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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_execution_isr_exit
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ PUBLIC _tx_thread_context_restore
+_tx_thread_context_restore:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_save.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_save.s
new file mode 100644
index 00000000..5c31541b
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_save.s
@@ -0,0 +1,80 @@
+/**************************************************************************/
+/* */
+/* 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_execution_isr_enter
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is only needed for legacy applications and it should */
+/* not be called in any new development on a Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ PUBLIC _tx_thread_context_save
+_tx_thread_context_save:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ /* Context is already saved - just return. */
+
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_control.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_control.s
new file mode 100644
index 00000000..ef1686e3
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_control.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ PUBLIC _tx_thread_interrupt_control
+_tx_thread_interrupt_control:
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_disable.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_disable.s
new file mode 100644
index 00000000..dc845dc1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_disable.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ PUBLIC _tx_thread_interrupt_disable
+_tx_thread_interrupt_disable:
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_restore.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_restore.s
new file mode 100644
index 00000000..0fb7ff30
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_interrupt_restore.s
@@ -0,0 +1,75 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ PUBLIC _tx_thread_interrupt_restore
+_tx_thread_interrupt_restore:
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s
new file mode 100644
index 00000000..727ff0f1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s
@@ -0,0 +1,318 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_execute_ptr
+ EXTERN _tx_timer_time_slice
+ EXTERN _tx_thread_preempt_disable
+ EXTERN _tx_execution_thread_enter
+ EXTERN _tx_execution_thread_exit
+#ifdef TX_LOW_POWER
+ EXTERN tx_low_power_enter
+ EXTERN tx_low_power_exit
+#endif
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/IAR */
+/* 6.1.11 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ PUBLIC _tx_thread_schedule
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+
+#ifdef __ARMVFP__
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ PUBLIC PendSV_Handler
+ PUBLIC __tx_PendSVHandler
+PendSV_Handler:
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARMVFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARMVFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+#ifdef __ARMVFP__
+
+ PUBLIC tx_thread_fpu_enable
+tx_thread_fpu_enable:
+ PUBLIC tx_thread_fpu_disable
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+#endif
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_stack_build.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_stack_build.s
new file mode 100644
index 00000000..10380569
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_stack_build.s
@@ -0,0 +1,132 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ PUBLIC _tx_thread_stack_build
+_tx_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s
new file mode 100644
index 00000000..313d2a40
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mx/IAR */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ PUBLIC _tx_thread_system_return
+_tx_thread_system_return:
+
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context:
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_timer_interrupt.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_timer_interrupt.s
new file mode 100644
index 00000000..b7ba9981
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_timer_interrupt.s
@@ -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 */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ EXTERN _tx_timer_time_slice
+ EXTERN _tx_timer_system_clock
+ EXTERN _tx_timer_current_ptr
+ EXTERN _tx_timer_list_start
+ EXTERN _tx_timer_list_end
+ EXTERN _tx_timer_expired_time_slice
+ EXTERN _tx_timer_expired
+ EXTERN _tx_thread_time_slice
+ EXTERN _tx_timer_expiration_process
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_execute_ptr
+ EXTERN _tx_thread_preempt_disable
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mx/IAR */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comment(s), added */
+/* TX_NO_TIMER support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+#ifndef TX_NO_TIMER
+ PUBLIC _tx_timer_interrupt
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ STMDB sp!, {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+#endif
+ END
diff --git a/ports_arch/ARMv7-M/threadx/iar/tx_low_power.c b/ports_arch/ARMv7-M/threadx/iar/tx_low_power.c
new file mode 100644
index 00000000..fc09ff50
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/tx_low_power.c
@@ -0,0 +1,563 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Low Power Timer Management */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_low_power.h"
+
+
+/* Define low power global variables. */
+
+/* Flag to determine if we've entered low power mode or not. */
+UINT tx_low_power_entered;
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tx_low_power_enter PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is the low power entry function. This function is */
+/* assumed to be called from the idle loop of tx_thread_schedule. It */
+/* is important to note that if an interrupt managed by ThreadX occurs */
+/* anywhere where interrupts are enabled in this function, the entire */
+/* processing of this function is discarded and the function won't be */
+/* re-entered until the idle loop in tx_thread_schedule is executed */
+/* again. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_timer_get_next Get next timer expiration */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_schedule Thread scheduling loop */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID tx_low_power_enter(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+ULONG tx_low_power_next_expiration;
+ULONG any_expired;
+
+
+ /* The below macro is user-defined code to determine
+ if low power mode is beneficial for the application.
+ Reasons for not entering low power mode include
+ the overhead associated with entering and exiting low power mode
+ outweighs the savings given when the next interrupt is expected.
+ In addition, the application might also be in a state where
+ responsiveness is more important than power savings. In such
+ situations, using a "reduced power mode" might make more sense.
+ In any case, if low power mode is not desired, simply return at
+ this point in the code. */
+ #ifdef TX_LOW_POWER_USER_CHECK
+ TX_LOW_POWER_USER_CHECK;
+ #endif
+
+ /* Disable interrupts while we prepare for low power mode. */
+ TX_DISABLE
+
+ /* At this point, we want to enter low power mode, since nothing
+ meaningful is going on in the system. However, in order to keep
+ the ThreadX timer services accurate, we must first determine the
+ next ThreadX timer expiration in terms of ticks. This is
+ accomplished via the tx_timer_get_next API. */
+ any_expired = tx_timer_get_next(&tx_low_power_next_expiration);
+
+ /* There are two possibilities:
+ 1: A ThreadX timer is active. tx_timer_get_next returns TX_TRUE.
+ Program the hardware timer source such that the next timer
+ interrupt is equal to: tx_low_power_next_expiration*tick_frequency.
+ In most applications, the tick_frequency is 10ms, but this is
+ completely application specific in ThreadX, typically set up
+ in tx_low_level_initialize.
+ 2: There are no ThreadX timers active. tx_timer_get_next returns TX_FALSE.
+ If you don't care about maintaining the ThreadX system clock, you can simply
+ sleep forever (until an interrupt wakes you up).
+ If you do want to maintain the ThreadX system clock,
+ program the hardware timer so you can keep track of elapsed time. */
+ #ifdef TX_LOW_POWER_USER_TIMER_SETUP
+ TX_LOW_POWER_USER_TIMER_SETUP(any_expired, tx_low_power_next_expiration);
+ #endif
+
+
+ /* Set the flag indicating that low power has been entered. This
+ flag is checked in tx_low_power_exit to determine if the logic
+ used to adjust the ThreadX time is required. */
+ tx_low_power_entered = TX_TRUE;
+
+ /* Re-enable interrupts before low power mode is entered. */
+ TX_RESTORE
+
+ /* User code to enter low power mode. */
+ #ifdef TX_LOW_POWER_USER_ENTER
+ TX_LOW_POWER_USER_ENTER;
+ #endif
+
+ /* If the low power code returns, this routine returns to the
+ tx_thread_schedule loop. */
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tx_low_power_exit PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is the low power exit function. This function must */
+/* be called from any interrupt that can wakeup the processor from */
+/* low power mode. If nothing needs to be done, this function simply */
+/* returns. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_time_increment Update the ThreadX timer */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Front-end of Interrupt */
+/* Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID tx_low_power_exit(VOID)
+{
+ULONG tx_low_power_adjust_ticks;
+
+ /* Determine if the interrupt occurred in low power mode. */
+ if (tx_low_power_entered)
+ {
+
+ /* Yes, low power mode was interrupted. */
+
+ /* Clear the low power entered flag. */
+ tx_low_power_entered = TX_FALSE;
+
+ /* User code to exit low power mode and reprogram the
+ timer to the desired interrupt frequency. */
+ #ifdef TX_LOW_POWER_USER_EXIT
+ TX_LOW_POWER_USER_EXIT;
+ #endif
+
+ /* User code to determine how many timer ticks (interrupts) that
+ the ThreadX time should be incremented to properly adjust
+ for the time in low power mode. The result is assumed to be
+ placed in tx_low_power_adjust_ticks. */
+ #ifdef TX_LOW_POWER_USER_TIMER_ADJUST
+ tx_low_power_adjust_ticks = TX_LOW_POWER_USER_TIMER_ADJUST;
+ #else
+ tx_low_power_adjust_ticks = (ULONG)0;
+ #endif
+
+ /* Determine if the ThreadX timer needs incrementing. */
+ if (tx_low_power_adjust_ticks)
+ {
+
+ /* Yes, the ThreadX time must be incremented. Call tx_time_increment
+ to accomplish this. */
+ tx_time_increment(tx_low_power_adjust_ticks);
+ }
+ }
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tx_timer_get_next PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calculates the next expiration time minus 1 tick for */
+/* the currently active ThreadX timers. If no timer is active, this */
+/* routine will return a value of TX_FALSE and the next ticks value */
+/* will be set to zero. */
+/* */
+/* INPUT */
+/* */
+/* next_timer_tick_ptr Pointer to destination for next */
+/* timer expiration value */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE (1) At least one timer is active */
+/* TX_FALSE (0) No timers are currently active */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* tx_low_power_enter */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+ULONG tx_timer_get_next(ULONG *next_timer_tick_ptr)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_TIMER_INTERNAL **timer_list_head;
+TX_TIMER_INTERNAL *next_timer;
+UINT i;
+ULONG calculated_time;
+ULONG expiration_time = (ULONG) 0xFFFFFFFF;
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Look at the next timer entry. */
+ timer_list_head = _tx_timer_current_ptr;
+
+ /* Loop through the timer list, looking for the first non-NULL
+ value to signal an active timer. */
+ for (i = (UINT)0; i < TX_TIMER_ENTRIES; i++)
+ {
+
+ /* Now determine if there is an active timer in this slot. */
+ if (*timer_list_head)
+ {
+
+ /* Setup the pointer to the expiration list. */
+ next_timer = *timer_list_head;
+
+ /* Loop through the timers active for this relative time slot (determined by i). */
+ do
+ {
+
+ /* Determine if the remaining time is larger than the list. */
+ if (next_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Calculate the expiration time. */
+ calculated_time = next_timer -> tx_timer_internal_remaining_ticks - (TX_TIMER_ENTRIES - i);
+ }
+ else
+ {
+
+ /* Calculate the expiration time, which is simply the number of entries in this case. */
+ calculated_time = i;
+ }
+
+ /* Determine if a new minimum expiration time is present. */
+ if (expiration_time > calculated_time)
+ {
+
+ /* Yes, a new minimum expiration time is present - remember it! */
+ expiration_time = calculated_time;
+ }
+
+ /* Move to the next entry in the timer list. */
+ next_timer = next_timer -> tx_timer_internal_active_next;
+
+ } while (next_timer != *timer_list_head);
+ }
+
+ /* This timer entry is NULL, so just move to the next one. */
+ timer_list_head++;
+
+ /* Check for timer list wrap condition. */
+ if (timer_list_head >= _tx_timer_list_end)
+ {
+
+ /* Wrap to the beginning of the list. */
+ timer_list_head = _tx_timer_list_start;
+ }
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Determine if an active timer was found. */
+ if (expiration_time != 0xFFFFFFFF)
+ {
+
+ /* Yes, an active timer was found. */
+ *next_timer_tick_ptr = expiration_time;
+ return(TX_TRUE);
+ }
+ else
+ {
+
+ /* No active timer was found. */
+ *next_timer_tick_ptr = 0;
+ return(TX_FALSE);
+ }
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tx_time_increment PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function increments the current time by a specified value. */
+/* The value was derived by the application by calling the */
+/* tx_timer_get_next function prior to this call, which was right */
+/* before the processor was put in sleep mode. */
+/* */
+/* INPUT */
+/* */
+/* time_increment The amount of time to catch up on */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_system_activate Timer activate service */
+/* */
+/* CALLED BY */
+/* */
+/* tx_low_power_exit */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+VOID tx_time_increment(ULONG time_increment)
+{
+
+TX_INTERRUPT_SAVE_AREA
+UINT i;
+TX_TIMER_INTERNAL **timer_list_head;
+TX_TIMER_INTERNAL *next_timer;
+TX_TIMER_INTERNAL *temp_list_head;
+
+
+ /* Determine if there is any time increment. */
+ if (time_increment == 0)
+ {
+
+ /* Nothing to do, just return. */
+ return;
+ }
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* Adjust the system clock. */
+ _tx_timer_system_clock = _tx_timer_system_clock + time_increment;
+
+ /* Adjust the time slice variable. */
+ if (_tx_timer_time_slice)
+ {
+
+ /* Decrement the time-slice variable. */
+ if (_tx_timer_time_slice > time_increment)
+ _tx_timer_time_slice = _tx_timer_time_slice - time_increment;
+ else
+ _tx_timer_time_slice = 1;
+ }
+
+ /* Calculate the proper place to position the timer. */
+ timer_list_head = _tx_timer_current_ptr;
+
+ /* Setup the temporary list pointer. */
+ temp_list_head = TX_NULL;
+
+ /* Loop to pull all timers off the timer structure and put on the
+ the temporary list head. */
+ for (i = 0; i < TX_TIMER_ENTRIES; i++)
+ {
+
+ /* Determine if there is a timer list in this entry. */
+ if (*timer_list_head)
+ {
+
+ /* Walk the list and update all the relative times to actual times. */
+
+ /* Setup the pointer to the expiration list. */
+ next_timer = *timer_list_head;
+
+ /* Loop through the timers active for this relative time slot (determined by i). */
+ do
+ {
+
+ /* Determine if the remaining time is larger than the list. */
+ if (next_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
+ {
+
+ /* Calculate the actual expiration time. */
+ next_timer -> tx_timer_internal_remaining_ticks =
+ next_timer -> tx_timer_internal_remaining_ticks - (TX_TIMER_ENTRIES - i) + 1;
+ }
+ else
+ {
+
+ /* Calculate the expiration time, which is simply the number of entries in this
+ case. */
+ next_timer -> tx_timer_internal_remaining_ticks = i + 1;
+ }
+
+ /* Move to the next entry in the timer list. */
+ next_timer = next_timer -> tx_timer_internal_active_next;
+
+ } while (next_timer != *timer_list_head);
+
+ /* NULL terminate the current timer list. */
+ ((*timer_list_head) -> tx_timer_internal_active_previous) -> tx_timer_internal_active_next = TX_NULL;
+
+ /* Yes, determine if the temporary list is NULL. */
+ if (temp_list_head == TX_NULL)
+ {
+
+ /* First item on the list. Move the entire
+ linked list. */
+ temp_list_head = *timer_list_head;
+ }
+ else
+ {
+
+ /* No, the temp list already has timers on it. Link the next
+ timer list to the end. */
+ (temp_list_head -> tx_timer_internal_active_previous) -> tx_timer_internal_active_next = *timer_list_head;
+
+ /* Now update the previous to the new list's previous timer pointer. */
+ temp_list_head -> tx_timer_internal_active_previous = (*timer_list_head) -> tx_timer_internal_active_previous;
+ }
+
+ /* Now clear the current timer head pointer. */
+ *timer_list_head = TX_NULL;
+ }
+
+ /* Move to next timer entry. */
+ timer_list_head++;
+
+ /* Determine if a wrap around condition has occurred. */
+ if (timer_list_head >= _tx_timer_list_end)
+ {
+
+ /* Wrap from the beginning of the list. */
+ timer_list_head = _tx_timer_list_start;
+ }
+ }
+
+ /* Set the current timer pointer to the beginning of the list. */
+ _tx_timer_current_ptr = _tx_timer_list_start;
+
+ /* Loop to update and reinsert all the timers in the list. */
+ while (temp_list_head)
+ {
+
+ /* Pickup the next timer to update and reinsert. */
+ next_timer = temp_list_head;
+
+ /* Move the temp list head pointer to the next pointer. */
+ temp_list_head = next_timer -> tx_timer_internal_active_next;
+
+ /* Determine if the remaining time is greater than the time increment
+ value - this is the normal case. */
+ if (next_timer -> tx_timer_internal_remaining_ticks > time_increment)
+ {
+
+ /* Decrement the elapsed time. */
+ next_timer -> tx_timer_internal_remaining_ticks = next_timer -> tx_timer_internal_remaining_ticks - time_increment;
+ }
+ else
+ {
+
+ /* Simply set the expiration value to expire on the next tick. */
+ next_timer -> tx_timer_internal_remaining_ticks = 1;
+ }
+
+ /* Now clear the timer list head pointer for the timer activate function to work properly. */
+ next_timer -> tx_timer_internal_list_head = TX_NULL;
+
+ /* Now re-insert the timer into the list. */
+ _tx_timer_system_activate(next_timer);
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
diff --git a/ports_arch/ARMv7-M/threadx/iar/tx_low_power.h b/ports_arch/ARMv7-M/threadx/iar/tx_low_power.h
new file mode 100644
index 00000000..47b9228b
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/iar/tx_low_power.h
@@ -0,0 +1,58 @@
+/**************************************************************************/
+/* */
+/* 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 Management */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_low_power.h PORTABLE C */
+/* 6.0 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines prototypes for the low-power timer additions */
+/* required for sleep mode. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 05-19-2020 William E. Lamie Initial Version 6.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_LOW_POWER_H
+#define TX_LOW_POWER_H
+
+
+/* Define low-power function prototypes. */
+
+VOID tx_low_power_enter(VOID);
+VOID tx_low_power_exit(VOID);
+VOID tx_time_increment(ULONG time_increment);
+ULONG tx_timer_get_next(ULONG *next_timer_tick_ptr);
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/inc/tx_port.h
new file mode 100644
index 00000000..14a5f775
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx/inc/tx_port.h
@@ -0,0 +1,729 @@
+/**************************************************************************/
+/* */
+/* 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 Cortex-Mx */
+/* 6.1.12 */
+/* */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
+/* the ARMv7-M architecture and compilers into one common file. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 01-31-2022 Scott Larson Modified comments, updated */
+/* typedef to fix misra */
+/* violation, */
+/* fixed predefined macro, */
+/* resulting in version 6.1.10 */
+/* 04-25-2022 Scott Larson Modified comments and added */
+/* volatile to registers, */
+/* resulting in version 6.1.11 */
+/* 07-29-2022 Scott Larson Modified comments and */
+/* described BASEPRI usage, */
+/* resulting in version 6.1.12 */
+/* */
+/**************************************************************************/
+
+#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 compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __ICCARM__
+#include <intrinsics.h> /* IAR Intrinsics */
+#define __asm__ __asm /* Define to make all inline asm look similar */
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+#endif /* __ICCARM__ */
+
+#ifdef __ghs__
+#include <arm_ghs.h>
+#include "tx_ghs.h"
+#endif /* __ghs__ */
+
+
+#if !defined(__GNUC__) && !defined(__CC_ARM)
+#define __get_control_value __get_CONTROL
+#define __set_control_value __set_CONTROL
+#endif
+
+#ifndef __GNUC__
+#define __get_ipsr_value __get_IPSR
+#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 unsigned long long ULONG64;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#define ULONG64_DEFINED
+
+/* 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 200 /* 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
+
+/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts.
+If using BASEPRI is desired, define the following two symbols for both c and assembly files:
+TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK.
+TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask.
+Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run.
+*/
+
+/* Define various constants for the ThreadX Cortex-M port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* 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 *((volatile ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
+#endif
+#else
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#endif
+
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+#ifdef __ghs__
+/* Define constants for Green Hills EventAnalyzer. */
+
+/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
+ represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
+
+#define TX_EL_TICKS_PER_SECOND 1000000
+
+/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
+ simulate the time-stamp source with a counter. */
+
+#define read_tbu() _tx_el_time_base_upper
+#define read_tbl() ++_tx_el_time_base_lower
+#endif /* __ghs__ */
+
+/* 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. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* 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. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#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
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#elif defined(__ghs__)
+#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
+ int Errno; /* errno. */ \
+ char * strtok_saved_pos; /* strtok() position. */
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+
+#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. */
+
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#if (__VER__ < 8000000)
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
+#else
+void *_tx_iar_create_per_thread_tls_area(void);
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+void __iar_Initlocks(void);
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
+#endif
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
+
+#ifdef TX_MISRA_ENABLE
+
+ULONG _tx_misra_control_get(void);
+void _tx_misra_control_set(ULONG value);
+ULONG _tx_misra_fpccr_get(void);
+void _tx_misra_vfp_touch(void);
+
+#else /* TX_MISRA_ENABLE not defined */
+
+/* Define some helper functions (these are intrinsics in some compilers). */
+#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
+
+__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
+{
+ULONG control_value;
+
+ __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
+ return(control_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
+{
+ __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
+}
+
+#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
+
+#elif defined(__CC_ARM) /* ARM Compiler 5 */
+
+__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
+{
+ULONG control_value;
+
+ __asm volatile ("MRS control_value,CONTROL");
+ return(control_value);
+}
+
+__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
+{
+ __asm__ volatile ("MSR CONTROL,control_value");
+}
+/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
+void _tx_vfp_access(void);
+#define TX_VFP_TOUCH() _tx_vfp_access();
+
+#elif defined(__ICCARM__) /* IAR */
+#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
+#endif /* Helper functions for different compilers */
+
+#endif /* TX_MISRA_ENABLE */
+
+
+/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
+ in order to ensure no lazy stacking will occur. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control_value(_tx_vfp_state); \
+ }
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ }
+
+#endif
+
+/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
+ If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
+ this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
+ the lazy FPU save, then restore the CONTROL.FPCA state. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control_value(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ TX_VFP_TOUCH(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control_value(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#else
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = _tx_misra_fpccr_get(); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ _tx_misra_vfp_touch(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#endif
+
+#else /* No VFP in use */
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
+
+
+/* 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 the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+#ifdef __CC_ARM /* ARM Compiler 5 */
+
+register unsigned int _ipsr __asm("ipsr");
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
+
+#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
+{
+unsigned int ipsr_value;
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
+
+#elif defined(__ICCARM__) /* IAR */
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
+
+#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
+
+#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif /* TX_MISRA_ENABLE */
+#endif /* TX_THREAD_GET_SYSTEM_STATE */
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
+ for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
+ zero after initialization for Cortex-M ports. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
+#ifdef __ICCARM__ /* IAR Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
+#elif defined(__CC_ARM) /* AC5 Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
+#elif defined(__GNUC__) /* GCC and AC6 Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
+ __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
+#endif
+
+
+
+/* Define the interrupt disable/restore macros for each compiler. */
+
+#if defined(__GNUC__) || defined(__ICCARM__)
+
+/*** GCC/AC6 and IAR ***/
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
+{
+unsigned int posture;
+#ifdef TX_PORT_USE_BASEPRI
+ __asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
+#else
+ __asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
+#endif
+ return(posture);
+}
+
+#ifdef TX_PORT_USE_BASEPRI
+__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
+{
+ __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
+}
+#else
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+ __asm__ volatile ("CPSIE i": : : "memory");
+}
+#endif
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
+{
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(int_posture);
+ //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
+#else
+ __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
+#endif
+}
+
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
+unsigned int int_posture;
+
+ int_posture = __get_interrupt_posture();
+
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(TX_PORT_BASEPRI);
+#else
+ __asm__ volatile ("CPSID i" : : : "memory");
+#endif
+ return(int_posture);
+}
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ /* Set PendSV to invoke ThreadX scheduler. */
+ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (__get_ipsr_value() == 0)
+ {
+ interrupt_save = __get_interrupt_posture();
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(0);
+#else
+ __enable_interrupts();
+#endif
+ __restore_interrupt(interrupt_save);
+ }
+}
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupt(interrupt_save);
+
+/*** End GCC/AC6 and IAR ***/
+
+#elif defined(__CC_ARM)
+
+/*** AC5 ***/
+
+static __inline unsigned int __get_interrupt_posture(void)
+{
+unsigned int posture;
+#ifdef TX_PORT_USE_BASEPRI
+ __asm__ volatile ("MRS #posture, BASEPRI");
+#else
+ __asm__ volatile ("MRS #posture, PRIMASK");
+#endif
+ return(posture);
+}
+
+#ifdef TX_PORT_USE_BASEPRI
+static __inline void __set_basepri_value(unsigned int basepri_value)
+{
+ __asm__ volatile ("MSR BASEPRI, #basepri_value");
+}
+#endif
+
+static __inline unsigned int __disable_interrupts(void)
+{
+unsigned int int_posture;
+
+ int_posture = __get_interrupt_posture();
+
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(TX_PORT_BASEPRI);
+#else
+ __asm__ volatile ("CPSID i");
+#endif
+ return(int_posture);
+}
+
+static __inline void __restore_interrupt(unsigned int int_posture)
+{
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(int_posture);
+#else
+ __asm__ volatile ("MSR PRIMASK, #int_posture");
+#endif
+}
+
+static void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ /* Set PendSV to invoke ThreadX scheduler. */
+ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (_ipsr == 0)
+ {
+#ifdef TX_PORT_USE_BASEPRI
+ interrupt_save = __get_interrupt_posture();
+ __set_basepri_value(0);
+ __set_basepri_value(interrupt_save);
+#else
+ interrupt_save = __disable_irq();
+ __enable_irq();
+ if (interrupt_save != 0)
+ __disable_irq();
+#endif
+ }
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupt(interrupt_save);
+
+/*** End AC5 ***/
+
+#endif /* Interrupt disable/restore macros for each compiler. */
+
+/* Redefine _tx_thread_system_return for improved performance. */
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+
+#else /* TX_DISABLE_INLINE is defined */
+
+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);
+#endif /* TX_DISABLE_INLINE */
+
+
+/* Define FPU extension for the Cortex-M. Each is assumed to be called in the context of the executing
+ thread. These are no longer needed, but are preserved for backward compatibility only. */
+
+void tx_thread_fpu_enable(void);
+void tx_thread_fpu_disable(void);
+
+
+/* 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 Cortex-Mx Version 6.2.1 *";
+#else
+#ifdef TX_MISRA_ENABLE
+extern CHAR _tx_version_id[100];
+#else
+extern CHAR _tx_version_id[];
+#endif
+#endif
+
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_initialize.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_initialize.s
new file mode 100644
index 00000000..4a721c20
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_initialize.s
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT __use_two_region_memory
+ IMPORT __scatterload
+ IMPORT txm_heap
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_initialize Cortex-Mx/AC5 */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the module c runtime. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* __scatterload Initialize C runtime */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_thread_shell_entry Start module thread */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_initialize(VOID)
+
+ EXPORT _txm_module_initialize
+_txm_module_initialize
+ PUSH {r4-r12,lr} // Save dregs and LR
+
+ B __scatterload // Call ARM func to initialize variables
+
+
+/* Override __rt_exit function. */
+
+ EXPORT __rt_exit
+__rt_exit
+
+ POP {r4-r12,lr} // Restore dregs and LR
+ BX lr // Return to caller
+
+ EXPORT __user_setup_stackheap
+ // returns heap start address in R0
+ // returns heap end address in R2
+ // does not touch SP, it is already set up before the module runs
+
+__user_setup_stackheap
+ LDR r1, _tx_heap_offset // load heap offset
+ ADD r0, r9, r1 // calculate heap base address
+ MOV r2, #TXM_MODULE_HEAP_SIZE // load heap size
+ ADD r2, r2, r0 // calculate heap end address
+ BX lr
+
+ ALIGN 4
+_tx_heap_offset
+ DCDO txm_heap
+ AREA ||.arm_vfe_header||, DATA, READONLY, NOALLOC, ALIGN=2
+
+ IMPORT txm_heap [DATA]
+
+
+// Dummy main function
+
+ AREA section_main, CODE, READONLY, ALIGN=2
+ EXPORT main
+main
+ BX lr
+
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_thread_shell_entry.c b/ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_thread_shell_entry.c
new file mode 100644
index 00000000..1f87ca65
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_lib/src/txm_module_thread_shell_entry.c
@@ -0,0 +1,174 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TXM_MODULE
+#define TXM_MODULE
+#endif
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "txm_module.h"
+#include "tx_thread.h"
+
+/* Define the global module entry pointer from the start thread of the module. */
+
+TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
+
+
+/* Define the dispatch function pointer used in the module implementation. */
+
+ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
+
+
+/* Define the startup code that clears the uninitialized global data and sets up the
+ preset global variables. */
+
+extern VOID _txm_module_initialize(VOID);
+
+__align(8) UCHAR txm_heap[TXM_MODULE_HEAP_SIZE];
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_thread_shell_entry Cortex-Mx/AC5 */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calls the specified entry function of the thread. It */
+/* also provides a place for the thread's entry function to return. */
+/* If the thread returns, this function places the thread in a */
+/* "COMPLETED" state. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to current thread */
+/* thread_info Pointer to thread entry info */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_initialize cstartup initialization */
+/* thread_entry Thread's entry function */
+/* tx_thread_resume Resume the module callback thread */
+/* _txm_module_thread_system_suspend Module thread suspension routine */
+/* */
+/* CALLED BY */
+/* */
+/* Initial thread stack frame */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
+{
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+ VOID (*entry_exit_notify)(TX_THREAD *, UINT);
+#endif
+
+
+ /* Determine if this is the start thread. If so, we must prepare the module for
+ execution. If not, simply skip the C startup code. */
+ if (thread_info -> txm_module_thread_entry_info_start_thread)
+ {
+ /* Initialize the C environment. */
+ _txm_module_initialize();
+
+ /* Save the entry info pointer, for later use. */
+ _txm_module_entry_info = thread_info;
+
+ /* Save the kernel function dispatch address. This is used to make all resident calls from
+ the module. */
+ _txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
+
+ /* Ensure that we have a valid pointer. */
+ while (!_txm_module_kernel_call_dispatcher)
+ {
+ /* Loop here, if an error is present getting the dispatch function pointer!
+ An error here typically indicates the resident portion of _tx_thread_schedule
+ is not supporting the trap to obtain the function pointer. */
+ }
+
+ /* Resume the module's callback thread, already created in the manager. */
+ _txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
+ }
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has been entered! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
+ }
+#endif
+
+ /* Call current thread's entry function. */
+ (thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
+
+ /* Suspend thread with a "completed" state. */
+
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine again. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual thread suspension routine. */
+ _txm_module_thread_system_suspend(thread_ptr);
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s
new file mode 100644
index 00000000..6dcf71b1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s
@@ -0,0 +1,646 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_execute_ptr
+ IMPORT _tx_timer_time_slice
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ IMPORT _tx_execution_thread_enter
+ IMPORT _tx_execution_thread_exit
+#endif
+ IMPORT _tx_thread_preempt_disable
+ IMPORT _txm_module_manager_memory_fault_handler
+ IMPORT _txm_module_manager_memory_fault_info
+ IMPORT _txm_module_priv
+ IMPORT _txm_module_user_mode_exit
+
+ AREA ||.text||, CODE, READONLY
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/AC5 */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 04-25-2022 Scott Larson Optimized MPU configuration, */
+/* added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 07-29-2022 Scott Larson Removed the code path to skip */
+/* MPU reloading, optional */
+/* default MPU settings, */
+/* resulting in version 6.1.12 */
+/* 10-31-2022 Scott Larson Added low power support, */
+/* fixed label syntax, */
+/* resulting in version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ EXPORT _tx_thread_schedule
+_tx_thread_schedule
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __TARGET_FPU_VFP
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable memory fault registers. */
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, =0x70000 // Enable Usage, Bus, and MemManage faults
+ STR r1, [r0] //
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+
+ /* Memory Exception Handler. */
+
+ EXPORT MemManage_Handler
+MemManage_Handler
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+
+ /* Now pickup and store all the fault related information. */
+
+ LDR r12,=_txm_module_manager_memory_fault_info // Pickup fault info struct
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ STR r1, [r12, #0] // Save current thread pointer in fault info structure
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, [r0] // Pickup SHCSR
+ STR r1, [r12, #8] // Save SHCSR
+ LDR r0, =0xE000ED28 // Build CFSR address
+ LDR r1, [r0] // Pickup CFSR
+ STR r1, [r12, #12] // Save CFSR
+ LDR r0, =0xE000ED34 // Build MMFAR address
+ LDR r1, [r0] // Pickup MMFAR
+ STR r1, [r12, #16] // Save MMFAR
+ LDR r0, =0xE000ED38 // Build BFAR address
+ LDR r1, [r0] // Pickup BFAR
+ STR r1, [r12, #20] // Save BFAR
+ MRS r0, CONTROL // Pickup current CONTROL register
+ STR r0, [r12, #24] // Save CONTROL
+ MRS r1, PSP // Pickup thread stack pointer
+ STR r1, [r12, #28] // Save thread stack pointer
+ LDR r0, [r1] // Pickup saved r0
+ STR r0, [r12, #32] // Save r0
+ LDR r0, [r1, #4] // Pickup saved r1
+ STR r0, [r12, #36] // Save r1
+ STR r2, [r12, #40] // Save r2
+ STR r3, [r12, #44] // Save r3
+ STR r4, [r12, #48] // Save r4
+ STR r5, [r12, #52] // Save r5
+ STR r6, [r12, #56] // Save r6
+ STR r7, [r12, #60] // Save r7
+ STR r8, [r12, #64] // Save r8
+ STR r9, [r12, #68] // Save r9
+ STR r10,[r12, #72] // Save r10
+ STR r11,[r12, #76] // Save r11
+ LDR r0, [r1, #16] // Pickup saved r12
+ STR r0, [r12, #80] // Save r12
+ LDR r0, [r1, #20] // Pickup saved lr
+ STR r0, [r12, #84] // Save lr
+ LDR r0, [r1, #24] // Pickup instruction address at point of fault
+ STR r0, [r12, #4] // Save point of fault
+ LDR r0, [r1, #28] // Pickup xPSR
+ STR r0, [r12, #88] // Save xPSR
+
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED28 // Build the Memory Management Fault Status Register (MMFSR)
+ LDRB r1, [r0] // Pickup the MMFSR, with the following bit definitions:
+ // Bit 0 = 1 -> Instruction address violation
+ // Bit 1 = 1 -> Load/store address violation
+ // Bit 7 = 1 -> MMFAR is valid
+ STRB r1, [r0] // Clear the MMFSR
+
+#ifdef __TARGET_FPU_VFP
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Save FPCCR
+#endif
+
+ BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+ CPSID i // Disable interrupts
+ BL _tx_execution_thread_exit // Call the thread exit function
+ CPSIE i // Enable interrupts
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from MemManage_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif
+ MOV lr, #0xFFFFFFFD // Load exception return code
+ BX lr // Return from exception
+
+
+ /* Generic context PendSV handler. */
+
+ EXPORT PendSV_Handler
+ EXPORT __tx_PendSVHandler
+PendSV_Handler
+__tx_PendSVHandler
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __TARGET_FPU_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBNZ r1, __tx_ts_restore // Yes, schedule it
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+__tx_ts_restore
+
+ /* A thread is ready, make the current thread the new thread
+ and enable interrupts. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+
+ MRS r5, CONTROL // Pickup current CONTROL register
+ LDR r4, [r1, #0x98] // Pickup current user mode flag
+ BIC r5, r5, #1 // Clear the UNPRIV bit
+ ORR r4, r4, r5 // Build new CONTROL register
+ MSR CONTROL, r4 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r3, #0 // Build disable value
+ CPSID i // Disable interrupts
+ STR r3, [r0] // Disable MPU
+ LDR r0, [r1, #0x90] // Pickup the module instance pointer
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r0, default_mpu // Is this thread owned by a module? No, default MPU setup
+#else
+ CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
+#endif
+
+ LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r2, default_mpu // Is protection required for this module? No, default MPU setup
+#else
+ CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
+#endif
+ LDR r1, =0xE000ED9C // MPU_RBAR register address
+
+ // Use alias registers to quickly load MPU
+ ADD r0, r0, #100 // Build address of MPU register start in thread control block
+
+#ifdef TXM_MODULE_MPU_DEFAULT
+ B config_mpu // configure MPU for module
+default_mpu
+ LDR r0, =txm_module_default_mpu_registers // default MPU configuration
+#endif
+
+config_mpu
+ LDM r0!,{r2-r9} // Load MPU regions 0-3
+ STM r1,{r2-r9} // Store MPU regions 0-3
+ LDM r0!,{r2-r9} // Load MPU regions 4-7
+ STM r1,{r2-r9} // Store MPU regions 4-7
+#ifdef TXM_MODULE_MANAGER_16_MPU
+ LDM r0!,{r2-r9} // Load MPU regions 8-11
+ STM r1,{r2-r9} // Store MPU regions 8-11
+ // Regions 12-15 are reserved for the user to define.
+ LDM r0,{r2-r9} // Load MPU regions 12-15
+ STM r1,{r2-r9} // Store MPU regions 12-15
+#endif
+_tx_enable_mpu
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r1, #5 // Build enable value with background region enabled
+ STR r1, [r0] // Enable MPU
+skip_mpu_setup
+ CPSIE i // Enable interrupts
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __TARGET_FPU_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+
+ /* SVC Handler. */
+
+ EXPORT SVC_Handler
+ EXPORT __tx_SVCallHandler
+SVC_Handler
+__tx_SVCallHandler
+ MRS r0, PSP // Pickup the PSP stack
+ LDR r1, [r0, #24] // Pickup the point of interrupt
+ LDRB r2, [r1, #-2] // Pickup the SVC parameter
+
+ /* Determine which SVC trap we are processing */
+
+ CMP r2, #1 // Is it the entry into ThreadX?
+ BNE _tx_thread_user_return // No, return to user mode
+
+ /* At this point we have an SVC 1, which means we are entering
+ the kernel from a module thread with user mode selected. */
+
+ LDR r2, =_txm_module_priv // Load address of where we should have come from
+ SUB r2, r2, #1 // Subtract 1 because of THUMB mode.
+ CMP r1, r2 // Did we come from user_mode_entry?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came.
+
+ LDR r3, [r0, #20] // This is the saved LR
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ MOV r1, #0 // Build clear value
+ STR r1, [r2, #0x98] // Clear the current user mode selection for thread
+ STR r3, [r2, #0xA0] // Save the original LR in thread control block
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_enter
+
+ /* Switch to the module thread's kernel stack */
+ LDR r0, [r2, #0xA8] // Load the module kernel stack end
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r1, [r2, #0xA4] // Load the module kernel stack start
+ LDR r3, [r2, #0xAC] // Load the module kernel stack size
+ STR r1, [r2, #12] // Set stack start
+ STR r0, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+ MRS r3, PSP // Pickup thread stack pointer
+#ifdef __TARGET_FPU_VFP
+ TST lr, #0x10 // Test for extended module stack
+ ITT EQ
+ ORREQ r3, r3, #1 // If so, set LSB in thread stack pointer to indicate extended frame
+ ORREQ lr, lr, #0x10 // Set bit, return with standard frame
+#endif
+ STR r3, [r2, #0xB0] // Save thread stack pointer
+#ifdef __TARGET_FPU_VFP
+ BIC r3, #1 // Clear possibly OR'd bit
+#endif
+
+ /* Build kernel stack by copying thread stack two registers at a time */
+ ADD r3, r3, #32 // Start at bottom of hardware stack
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+
+ MSR PSP, r0 // Set kernel stack pointer
+
+_tx_skip_kernel_stack_enter
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+_tx_thread_user_return
+ LDR r2, =_txm_module_user_mode_exit // Load address of where we should have come from
+ SUB r2, r2, #1 // Subtract 1 because of THUMB mode.
+ CMP r1, r2 // Did we come from user_mode_exit?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+ STR r1, [r2, #0x98] // Set the current user mode selection for thread
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_exit
+
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r0, [r2, #0xB4] // Load the module thread stack start
+ LDR r1, [r2, #0xB8] // Load the module thread stack end
+ LDR r3, [r2, #0xBC] // Load the module thread stack size
+ STR r0, [r2, #12] // Set stack start
+ STR r1, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+#ifdef __TARGET_FPU_VFP
+ /* If lazy stacking is pending, check if it can be cleared.
+ if(LSPACT && tx_thread_module_stack_start < FPCAR && FPCAR < tx_thread_module_stack_end)
+ then clear LSPACT. */
+ LDR r3, =0xE000EF34 // Address of FPCCR
+ LDR r3, [r3] // Load FPCCR
+ TST r3, #1 // Check if LSPACT is set
+ BEQ _tx_no_lazy_clear // if clear, move on
+ LDR r1, =0xE000EF38 // Address of FPCAR
+ LDR r1, [r1] // Load FPCAR
+ LDR r0, [r2, #0xA4] // Load kernel stack start
+ CMP r1, r0 // If FPCAR < start, move on
+ BLO _tx_no_lazy_clear
+ LDR r0, [r2, #0xA8] // Load kernel stack end
+ CMP r0, r1 // If end < FPCAR, move on
+ BLO _tx_no_lazy_clear
+ BIC r3, #1 // Clear LSPACT
+ LDR r1, =0xE000EF34 // Address of FPCCR
+ STR r3, [r1] // Save updated FPCCR
+_tx_no_lazy_clear
+#endif
+
+ LDR r0, [r2, #0xB0] // Load the module thread stack pointer
+ MRS r3, PSP // Pickup kernel stack pointer
+#ifdef __TARGET_FPU_VFP
+ TST r0, #1 // Is module stack extended?
+ ITTE NE // If so...
+ BICNE lr, #0x10 // Clear bit, return with extended frame
+ BICNE r0, #1 // Clear bit that indicates extended module frame
+ ORREQ lr, lr, #0x10 // Else set bit, return with standard frame
+#endif
+
+ /* Copy kernel hardware stack to module thread stack. */
+ LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
+ STM r0!, {r1-r2} // Insert r0, r1 into thread stack
+ LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
+ STM r0!, {r1-r2} // Insert r2, r3 into thread stack
+ LDM r3!, {r1-r2} // Get r12, lr from kernel stack
+ STM r0!, {r1-r2} // Insert r12, lr into thread stack
+ LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
+ STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
+ SUB r0, r0, #32 // Subtract 32 to get back to top of stack
+ MSR PSP, r0 // Set thread stack pointer
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+
+_tx_skip_kernel_stack_exit
+ MRS r0, CONTROL // Pickup current CONTROL register
+ ORR r0, r0, r1 // OR in the user mode bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+#ifdef __TARGET_FPU_VFP
+ EXPORT tx_thread_fpu_enable
+tx_thread_fpu_enable
+ EXPORT tx_thread_fpu_disable
+tx_thread_fpu_disable
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+ EXPORT _tx_vfp_access
+_tx_vfp_access
+ VMOV.F32 s0, s0 // Simply access the VFP
+ BX lr // Return to caller
+
+#endif
+
+ ALIGN 4
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_thread_stack_build.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_thread_stack_build.s
new file mode 100644
index 00000000..8b32e650
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_thread_stack_build.s
@@ -0,0 +1,138 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_thread_stack_build Cortex-Mx/AC5 */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* function_ptr Pointer to shell function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
+// {
+ EXPORT _txm_module_manager_thread_stack_build
+_txm_module_manager_thread_stack_build
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ lr Interrupted lr (lr at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r0, [r2, #36] // Store initial r0, which is the thread control block
+
+ LDR r3, [r0, #8] // Pickup thread entry info pointer,which is in the stack pointer position of the thread control block.
+ // It was setup in the txm_module_manager_thread_create function. It will be overwritten later in this
+ // function with the actual, initial stack pointer.
+ STR r3, [r2, #40] // Store initial r1, which is the module entry information.
+ LDR r3, [r3, #8] // Pickup data base register from the module information
+ STR r3, [r2, #24] // Store initial r9 (data base register)
+ MOV r3, #0 // Clear r3 again
+
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's control block
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_user_mode_entry.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_user_mode_entry.s
new file mode 100644
index 00000000..753bdb8c
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/txm_module_manager_user_mode_entry.s
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _txm_module_manager_kernel_dispatch
+ IMPORT _tx_thread_current_ptr
+
+ AREA ||.text||, CODE, READONLY, ALIGN=5
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_user_mode_entry Cortex-Mx/AC5 */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allows modules to enter kernel mode. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* SVC 1 Enter kernel mode */
+/* SVC 2 Exit kernel mode */
+/* */
+/* CALLED BY */
+/* */
+/* Modules in user mode */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_manager_user_mode_entry(VOID)
+// {
+ EXPORT _txm_module_manager_user_mode_entry
+_txm_module_manager_user_mode_entry
+ SVC 1 // Enter kernel
+ EXPORT _txm_module_priv
+_txm_module_priv
+ // At this point, we are out of user mode. The original LR has been saved in the
+ // thread control block. Simply call the kernel dispatch function.
+ BL _txm_module_manager_kernel_dispatch
+
+ // Pickup the original LR value while still in privileged mode
+ LDR r2, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r3, [r2] // Pickup current thread pointer
+ LDR lr, [r3, #0xA0] // Pickup saved LR from original call
+
+ SVC 2 // Exit kernel and return to user mode
+ EXPORT _txm_module_user_mode_exit
+_txm_module_user_mode_exit
+ BX lr // Return to the caller
+// }
+ ALIGN 32
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_initialize.S b/ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_initialize.S
new file mode 100644
index 00000000..ed3c8661
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_initialize.S
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .global __use_two_region_memory
+ .global __scatterload
+
+ .eabi_attribute Tag_ABI_PCS_RO_data, 1
+ .eabi_attribute Tag_ABI_PCS_R9_use, 1
+ .eabi_attribute Tag_ABI_PCS_RW_data, 2
+
+ .text
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_initialize Cortex-Mx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes the module c runtime. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* __scatterload Initialize C runtime */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_thread_shell_entry Start module thread */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 01-31-2022 Scott Larson Modified comments and made */
+/* heap user configurable, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_initialize(VOID)
+ .global _txm_module_initialize
+ .thumb_func
+_txm_module_initialize:
+ PUSH {r0-r12,lr} // Save dregs and LR
+ B __scatterload // Call ARM func to initialize variables
+
+// Override the __rt_exit function.
+ .global __rt_exit
+ .thumb_func
+__rt_exit:
+ POP {r4-r12,lr} // Restore dregs and LR
+ BX lr // Return to caller
+
+ .global __rt_entry
+ .type __rt_entry, %function
+__rt_entry:
+ POP {r0-r1}
+ BL __rt_lib_init
+ POP {r2-r12,lr} // Restore dregs and LR
+ BX lr // Return to caller
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_thread_shell_entry.c b/ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_thread_shell_entry.c
new file mode 100644
index 00000000..74139f55
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_lib/src/txm_module_thread_shell_entry.c
@@ -0,0 +1,178 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TXM_MODULE
+#define TXM_MODULE
+#endif
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "txm_module.h"
+#include "tx_thread.h"
+
+/* Define the global module entry pointer from the start thread of the module. */
+
+TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
+
+
+/* Define the dispatch function pointer used in the module implementation. */
+
+ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
+
+
+/* Define the module's heap and align it to 8 bytes. */
+__attribute__((aligned(8))) UCHAR txm_heap[TXM_MODULE_HEAP_SIZE];
+
+
+/* Use our asm routine that calls the ARM code to initialize data and heap. */
+extern VOID _txm_module_initialize(VOID *heap_base, VOID *heap_top);
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_thread_shell_entry Cortex-Mx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calls the specified entry function of the thread. It */
+/* also provides a place for the thread's entry function to return. */
+/* If the thread returns, this function places the thread in a */
+/* "COMPLETED" state. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to current thread */
+/* thread_info Pointer to thread entry info */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_initialize cstartup initialization */
+/* thread_entry Thread's entry function */
+/* tx_thread_resume Resume the module callback thread */
+/* _txm_module_thread_system_suspend Module thread suspension routine */
+/* */
+/* CALLED BY */
+/* */
+/* Initial thread stack frame */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 01-31-2022 Scott Larson Modified comments and made */
+/* heap user configurable, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
+{
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+ VOID (*entry_exit_notify)(TX_THREAD *, UINT);
+#endif
+
+
+ /* Determine if this is the start thread. If so, we must prepare the module for
+ execution. If not, simply skip the C startup code. */
+ if (thread_info -> txm_module_thread_entry_info_start_thread)
+ {
+ /* Initialize the C environment. */
+ _txm_module_initialize(&txm_heap[0], &txm_heap[TXM_MODULE_HEAP_SIZE-1]);
+
+ /* Save the entry info pointer, for later use. */
+ _txm_module_entry_info = thread_info;
+
+ /* Save the kernel function dispatch address. This is used to make all resident calls from
+ the module. */
+ _txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
+
+ /* Ensure that we have a valid pointer. */
+ while (!_txm_module_kernel_call_dispatcher)
+ {
+ /* Loop here, if an error is present getting the dispatch function pointer!
+ An error here typically indicates the resident portion of _tx_thread_schedule
+ is not supporting the trap to obtain the function pointer. */
+ }
+
+ /* Resume the module's callback thread, already created in the manager. */
+ _txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
+ }
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has been entered! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
+ }
+#endif
+
+ /* Call current thread's entry function. */
+ (thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
+
+ /* Suspend thread with a "completed" state. */
+
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine again. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual thread suspension routine. */
+ _txm_module_thread_system_suspend(thread_ptr);
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S
new file mode 100644
index 00000000..0dee2fd7
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S
@@ -0,0 +1,686 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_thread_preempt_disable
+ .global _txm_module_manager_memory_fault_handler
+ .global _txm_module_manager_memory_fault_info
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+#endif
+#ifdef TX_LOW_POWER
+ .global tx_low_power_enter
+ .global tx_low_power_exit
+#endif
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/AC6 */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 04-25-2022 Scott Larson Optimized MPU configuration, */
+/* added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 07-29-2022 Scott Larson Removed the code path to skip */
+/* MPU reloading, optional */
+/* default MPU settings, */
+/* resulting in version 6.1.12 */
+/* 10-31-2022 Scott Larson Added low power support, */
+/* resulting in version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __ARM_FP
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable memory fault registers. */
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, =0x70000 // Enable Usage, Bus, and MemManage faults
+ STR r1, [r0] //
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+
+ /* Memory Exception Handler. */
+ .global MemManage_Handler
+ .global BusFault_Handler
+ .global UsageFault_Handler
+ .thumb_func
+MemManage_Handler:
+ .thumb_func
+BusFault_Handler:
+ .thumb_func
+UsageFault_Handler:
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+
+ /* Now pickup and store all the fault related information. */
+
+ LDR r12,=_txm_module_manager_memory_fault_info // Pickup fault info struct
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ STR r1, [r12, #0] // Save current thread pointer in fault info structure
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, [r0] // Pickup SHCSR
+ STR r1, [r12, #8] // Save SHCSR
+ LDR r0, =0xE000ED28 // Build CFSR address
+ LDR r1, [r0] // Pickup CFSR
+ STR r1, [r12, #12] // Save CFSR
+ LDR r0, =0xE000ED34 // Build MMFAR address
+ LDR r1, [r0] // Pickup MMFAR
+ STR r1, [r12, #16] // Save MMFAR
+ LDR r0, =0xE000ED38 // Build BFAR address
+ LDR r1, [r0] // Pickup BFAR
+ STR r1, [r12, #20] // Save BFAR
+ MRS r0, CONTROL // Pickup current CONTROL register
+ STR r0, [r12, #24] // Save CONTROL
+ MRS r1, PSP // Pickup thread stack pointer
+ STR r1, [r12, #28] // Save thread stack pointer
+ LDR r0, [r1] // Pickup saved r0
+ STR r0, [r12, #32] // Save r0
+ LDR r0, [r1, #4] // Pickup saved r1
+ STR r0, [r12, #36] // Save r1
+ STR r2, [r12, #40] // Save r2
+ STR r3, [r12, #44] // Save r3
+ STR r4, [r12, #48] // Save r4
+ STR r5, [r12, #52] // Save r5
+ STR r6, [r12, #56] // Save r6
+ STR r7, [r12, #60] // Save r7
+ STR r8, [r12, #64] // Save r8
+ STR r9, [r12, #68] // Save r9
+ STR r10,[r12, #72] // Save r10
+ STR r11,[r12, #76] // Save r11
+ LDR r0, [r1, #16] // Pickup saved r12
+ STR r0, [r12, #80] // Save r12
+ LDR r0, [r1, #20] // Pickup saved lr
+ STR r0, [r12, #84] // Save lr
+ LDR r0, [r1, #24] // Pickup instruction address at point of fault
+ STR r0, [r12, #4] // Save point of fault
+ LDR r0, [r1, #28] // Pickup xPSR
+ STR r0, [r12, #88] // Save xPSR
+
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED28 // Build the Memory Management Fault Status Register (MMFSR)
+ LDRB r1, [r0] // Pickup the MMFSR, with the following bit definitions:
+ // Bit 0 = 1 -> Instruction address violation
+ // Bit 1 = 1 -> Load/store address violation
+ // Bit 7 = 1 -> MMFAR is valid
+ STRB r1, [r0] // Clear the MMFSR
+
+#ifdef __ARM_FP
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Save FPCCR
+#endif
+
+ BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+ CPSID i // Disable interrupts
+ BL _tx_execution_thread_exit // Call the thread exit function
+ CPSIE i // Enable interrupts
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from MemManage_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif
+ MOV lr, #0xFFFFFFFD // Load exception return code
+ BX lr // Return from exception
+
+
+ /* Generic context PendSV handler. */
+
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .syntax unified
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBNZ r1, __tx_ts_restore // Yes, schedule it
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+__tx_ts_restore:
+
+ /* A thread is ready, make the current thread the new thread
+ and enable interrupts. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+
+ MRS r5, CONTROL // Pickup current CONTROL register
+ LDR r4, [r1, #0x98] // Pickup current user mode flag
+ BIC r5, r5, #1 // Clear the UNPRIV bit
+ ORR r4, r4, r5 // Build new CONTROL register
+ MSR CONTROL, r4 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r3, #0 // Build disable value
+ CPSID i // Disable interrupts
+ STR r3, [r0] // Disable MPU
+ LDR r0, [r1, #0x90] // Pickup the module instance pointer
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r0, default_mpu // Is this thread owned by a module? No, default MPU setup
+#else
+ CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
+#endif
+
+ LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r2, default_mpu // Is protection required for this module? No, default MPU setup
+#else
+ CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
+#endif
+ LDR r1, =0xE000ED9C // MPU_RBAR register address
+
+ // Use alias registers to quickly load MPU
+ ADD r0, r0, #100 // Build address of MPU register start in thread control block
+
+#ifdef TXM_MODULE_MPU_DEFAULT
+ B config_mpu // configure MPU for module
+default_mpu:
+ LDR r0, =txm_module_default_mpu_registers // default MPU configuration
+#endif
+
+config_mpu:
+ LDM r0!,{r2-r9} // Load MPU regions 0-3
+ STM r1,{r2-r9} // Store MPU regions 0-3
+ LDM r0!,{r2-r9} // Load MPU regions 4-7
+ STM r1,{r2-r9} // Store MPU regions 4-7
+#ifdef TXM_MODULE_MANAGER_16_MPU
+ LDM r0!,{r2-r9} // Load MPU regions 8-11
+ STM r1,{r2-r9} // Store MPU regions 8-11
+ // Regions 12-15 are reserved for the user to define.
+ LDM r0,{r2-r9} // Load MPU regions 12-15
+ STM r1,{r2-r9} // Store MPU regions 12-15
+#endif
+
+_tx_enable_mpu:
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r1, #5 // Build enable value with background region enabled
+ STR r1, [r0] // Enable MPU
+skip_mpu_setup:
+ CPSIE i // Enable interrupts
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+
+ /* SVC Handler. */
+
+ .global SVC_Handler
+ .thumb_func
+SVC_Handler:
+ .global __tx_SVCallHandler
+ .thumb_func
+__tx_SVCallHandler:
+
+ MRS r0, PSP // Pickup the PSP stack
+ LDR r1, [r0, #24] // Pickup the point of interrupt
+ LDRB r2, [r1, #-2] // Pickup the SVC parameter
+
+ /* Determine which SVC trap we are processing */
+
+ CMP r2, #1 // Is it the entry into ThreadX?
+ BNE _tx_thread_user_return // No, return to user mode
+
+ /* At this point we have an SVC 1, which means we are entering
+ the kernel from a module thread with user mode selected. */
+
+ LDR r2, =_txm_module_priv // Load address of where we should have come from
+ CMP r1, r2 // Did we come from user_mode_entry?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came.
+
+ LDR r3, [r0, #20] // This is the saved LR
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ MOV r1, #0 // Build clear value
+ STR r1, [r2, #0x98] // Clear the current user mode selection for thread
+ STR r3, [r2, #0xA0] // Save the original LR in thread control block
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_enter
+
+ /* Switch to the module thread's kernel stack */
+ LDR r0, [r2, #0xA8] // Load the module kernel stack end
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r1, [r2, #0xA4] // Load the module kernel stack start
+ LDR r3, [r2, #0xAC] // Load the module kernel stack size
+ STR r1, [r2, #12] // Set stack start
+ STR r0, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+ MRS r3, PSP // Pickup thread stack pointer
+#ifdef __ARM_FP
+ TST lr, #0x10 // Test for extended module stack
+ ITT EQ
+ ORREQ r3, r3, #1 // If so, set LSB in thread stack pointer to indicate extended frame
+ ORREQ lr, lr, #0x10 // Set bit, return with standard frame
+#endif
+ STR r3, [r2, #0xB0] // Save thread stack pointer
+#ifdef __ARM_FP
+ BIC r3, #1 // Clear possibly OR'd bit
+#endif
+
+ /* Build kernel stack by copying thread stack two registers at a time */
+ ADD r3, r3, #32 // Start at bottom of hardware stack
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+
+ MSR PSP, r0 // Set kernel stack pointer
+
+_tx_skip_kernel_stack_enter:
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+_tx_thread_user_return:
+ LDR r2, =_txm_module_user_mode_exit // Load address of where we should have come from
+ CMP r1, r2 // Did we come from user_mode_exit?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+ STR r1, [r2, #0x98] // Set the current user mode selection for thread
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_exit
+
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r0, [r2, #0xB4] // Load the module thread stack start
+ LDR r1, [r2, #0xB8] // Load the module thread stack end
+ LDR r3, [r2, #0xBC] // Load the module thread stack size
+ STR r0, [r2, #12] // Set stack start
+ STR r1, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+#ifdef __ARM_FP
+ /* If lazy stacking is pending, check if it can be cleared.
+ if(LSPACT && tx_thread_module_stack_start < FPCAR && FPCAR < tx_thread_module_stack_end)
+ then clear LSPACT. */
+ LDR r3, =0xE000EF34 // Address of FPCCR
+ LDR r3, [r3] // Load FPCCR
+ TST r3, #1 // Check if LSPACT is set
+ BEQ _tx_no_lazy_clear // if clear, move on
+ LDR r1, =0xE000EF38 // Address of FPCAR
+ LDR r1, [r1] // Load FPCAR
+ LDR r0, [r2, #0xA4] // Load kernel stack start
+ CMP r1, r0 // If FPCAR < start, move on
+ BLO _tx_no_lazy_clear
+ LDR r0, [r2, #0xA8] // Load kernel stack end
+ CMP r0, r1 // If end < FPCAR, move on
+ BLO _tx_no_lazy_clear
+ BIC r3, #1 // Clear LSPACT
+ LDR r1, =0xE000EF34 // Address of FPCCR
+ STR r3, [r1] // Save updated FPCCR
+_tx_no_lazy_clear:
+#endif
+
+ LDR r0, [r2, #0xB0] // Load the module thread stack pointer
+ MRS r3, PSP // Pickup kernel stack pointer
+#ifdef __ARM_FP
+ TST r0, #1 // Is module stack extended?
+ ITTE NE // If so...
+ BICNE lr, #0x10 // Clear bit, return with extended frame
+ BICNE r0, #1 // Clear bit that indicates extended module frame
+ ORREQ lr, lr, #0x10 // Else set bit, return with standard frame
+#endif
+
+ /* Copy kernel hardware stack to module thread stack. */
+ LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
+ STM r0!, {r1-r2} // Insert r0, r1 into thread stack
+ LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
+ STM r0!, {r1-r2} // Insert r2, r3 into thread stack
+ LDM r3!, {r1-r2} // Get r12, lr from kernel stack
+ STM r0!, {r1-r2} // Insert r12, lr into thread stack
+ LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
+ STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
+ SUB r0, r0, #32 // Subtract 32 to get back to top of stack
+ MSR PSP, r0 // Set thread stack pointer
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+
+_tx_skip_kernel_stack_exit:
+ MRS r0, CONTROL // Pickup current CONTROL register
+ ORR r0, r0, r1 // OR in the user mode bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+
+ /* Kernel entry function from user mode. */
+
+ .global _txm_module_manager_kernel_dispatch
+ .align 5
+ .syntax unified
+// VOID _txm_module_manager_user_mode_entry(VOID)
+// {
+ .global _txm_module_manager_user_mode_entry
+ .thumb_func
+_txm_module_manager_user_mode_entry:
+ SVC 1 // Enter kernel
+_txm_module_priv:
+ /* At this point, we are out of user mode. The original LR has been saved in the
+ thread control block. Simply call the kernel dispatch function. */
+ BL _txm_module_manager_kernel_dispatch
+
+ /* Pickup the original LR value while still in privileged mode */
+ LDR r2, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r3, [r2] // Pickup current thread pointer
+ LDR lr, [r3, #0xA0] // Pickup saved LR from original call
+
+ SVC 2 // Exit kernel and return to user mode
+_txm_module_user_mode_exit:
+ BX lr // Return to the caller
+ NOP
+ NOP
+ NOP
+ NOP
+// }
+
+#ifdef __ARM_FP
+
+ .global tx_thread_fpu_enable
+ .thumb_func
+tx_thread_fpu_enable:
+ .global tx_thread_fpu_disable
+ .thumb_func
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/txm_module_manager_thread_stack_build.S b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/txm_module_manager_thread_stack_build.S
new file mode 100644
index 00000000..3a3a2dcf
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/txm_module_manager_thread_stack_build.S
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_thread_stack_build Cortex-Mx/AC6 */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* function_ptr Pointer to shell function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
+// {
+ .global _txm_module_manager_thread_stack_build
+ .thumb_func
+_txm_module_manager_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ lr Interrupted lr (lr at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r0, [r2, #36] // Store initial r0, which is the thread control block
+
+ LDR r3, [r0, #8] // Pickup thread entry info pointer,which is in the stack pointer position of the thread control block.
+ // It was setup in the txm_module_manager_thread_create function. It will be overwritten later in this
+ // function with the actual, initial stack pointer.
+ STR r3, [r2, #40] // Store initial r1, which is the module entry information.
+ LDR r3, [r3, #8] // Pickup data base register from the module information
+ STR r3, [r2, #24] // Store initial r9 (data base register)
+ MOV r3, #0 // Clear r3 again
+
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's control block
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_alignment_adjust.c b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_alignment_adjust.c
new file mode 100644
index 00000000..e9a3b076
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_alignment_adjust.c
@@ -0,0 +1,448 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+#include "tx_api.h"
+#include "txm_module.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_power_of_two_block_size Cortex-Mx */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calculates a power of two size at or immediately above*/
+/* the input size and returns it to the caller. */
+/* */
+/* INPUT */
+/* */
+/* size Block size */
+/* */
+/* OUTPUT */
+/* */
+/* calculated size Rounded up to power of two */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_alignment_adjust Adjust alignment for Cortex-M */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+ULONG _txm_power_of_two_block_size(ULONG size)
+{
+ /* Check for 0 size. */
+ if(size == 0)
+ return 0;
+
+ /* Minimum MPU block size is 32. */
+ if(size <= 32)
+ return 32;
+
+ /* Bit twiddling trick to round to next high power of 2
+ (if original size is power of 2, it will return original size. Perfect!) */
+ size--;
+ size |= size >> 1;
+ size |= size >> 2;
+ size |= size >> 4;
+ size |= size >> 8;
+ size |= size >> 16;
+ size++;
+
+ /* Return a power of 2 size at or above the input size. */
+ return(size);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_alignment_adjust Cortex-Mx */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function adjusts the alignment and size of the code and data */
+/* section for a given module implementation. */
+/* */
+/* INPUT */
+/* */
+/* module_preamble Pointer to module preamble */
+/* code_size Size of the code area (updated) */
+/* code_alignment Code area alignment (updated) */
+/* data_size Size of data area (updated) */
+/* data_alignment Data area alignment (updated) */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _txm_power_of_two_block_size Calculate power of two size */
+/* */
+/* CALLED BY */
+/* */
+/* Initial thread stack frame */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble,
+ ULONG *code_size,
+ ULONG *code_alignment,
+ ULONG *data_size,
+ ULONG *data_alignment)
+{
+#ifdef TXM_MODULE_MANAGER_16_MPU
+ULONG local_code_size;
+ULONG local_code_alignment;
+ULONG local_data_size;
+ULONG local_data_alignment;
+ULONG code_size_accum;
+ULONG data_size_accum;
+
+ /* Copy the input parameters into local variables for ease of use. */
+ local_code_size = *code_size;
+ local_code_alignment = *code_alignment;
+ local_data_size = *data_size;
+ local_data_alignment = *data_alignment;
+
+ /* Determine code block sizes. Minimize the alignment requirement.
+ There are 4 MPU code entries available. The following is how the code size
+ will be distributed:
+ 1. 1/4 of the largest power of two that is greater than or equal to code size.
+ 2. 1/4 of the largest power of two that is greater than or equal to code size.
+ 3. Largest power of 2 that fits in the remaining space.
+ 4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
+ local_code_alignment = _txm_power_of_two_block_size(local_code_size) >> 2;
+ code_size_accum = local_code_alignment + local_code_alignment;
+ code_size_accum = code_size_accum + (_txm_power_of_two_block_size(local_code_size - code_size_accum) >> 1);
+ code_size_accum = code_size_accum + _txm_power_of_two_block_size(local_code_size - code_size_accum);
+ local_code_size = code_size_accum;
+
+ /* Determine data block sizes. Minimize the alignment requirement.
+ There are 4 MPU data entries available. The following is how the data size
+ will be distributed:
+ 1. 1/4 of the largest power of two that is greater than or equal to data size.
+ 2. 1/4 of the largest power of two that is greater than or equal to data size.
+ 3. Largest power of 2 that fits in the remaining space.
+ 4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
+ local_data_alignment = _txm_power_of_two_block_size(local_data_size) >> 2;
+ data_size_accum = local_data_alignment + local_data_alignment;
+ data_size_accum = data_size_accum + (_txm_power_of_two_block_size(local_data_size - data_size_accum) >> 1);
+ data_size_accum = data_size_accum + _txm_power_of_two_block_size(local_data_size - data_size_accum);
+ local_data_size = data_size_accum;
+
+ /* Return all the information to the caller. */
+ *code_size = local_code_size;
+ *code_alignment = local_code_alignment;
+ *data_size = local_data_size;
+ *data_alignment = local_data_alignment;
+
+#else
+
+ULONG local_code_size;
+ULONG local_code_alignment;
+ULONG local_data_size;
+ULONG local_data_alignment;
+ULONG code_block_size;
+ULONG data_block_size;
+ULONG code_size_accum;
+ULONG data_size_accum;
+
+ /* Copy the input parameters into local variables for ease of use. */
+ local_code_size = *code_size;
+ local_code_alignment = *code_alignment;
+ local_data_size = *data_size;
+ local_data_alignment = *data_alignment;
+
+
+ /* Test for external memory enabled in preamble. */
+ if(module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS)
+ {
+ /* External/shared memory enabled. TXM_MODULE_MANAGER_CODE_MPU_ENTRIES-1 code entries will be used. */
+ if (local_code_size <= (32*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 32 is best. */
+ code_block_size = 32;
+ }
+ else if (local_code_size <= (64*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 64 is best. */
+ code_block_size = 64;
+ }
+ else if (local_code_size <= (128*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 128 is best. */
+ code_block_size = 128;
+ }
+ else if (local_code_size <= (256*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 256 is best. */
+ code_block_size = 256;
+ }
+ else if (local_code_size <= (512*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 512 is best. */
+ code_block_size = 512;
+ }
+ else if (local_code_size <= (1024*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 1024 is best. */
+ code_block_size = 1024;
+ }
+ else if (local_code_size <= (2048*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 2048 is best. */
+ code_block_size = 2048;
+ }
+ else if (local_code_size <= (4096*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 4096 is best. */
+ code_block_size = 4096;
+ }
+ else if (local_code_size <= (8192*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 8192 is best. */
+ code_block_size = 8192;
+ }
+ else if (local_code_size <= (16384*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 16384 is best. */
+ code_block_size = 16384;
+ }
+ else if (local_code_size <= (32768*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 32768 is best. */
+ code_block_size = 32768;
+ }
+ else if (local_code_size <= (65536*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 65536 is best. */
+ code_block_size = 65536;
+ }
+ else if (local_code_size <= (131072*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 131072 is best. */
+ code_block_size = 131072;
+ }
+ else if (local_code_size <= (262144*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 262144 is best. */
+ code_block_size = 262144;
+ }
+ else if (local_code_size <= (524288*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 524288 is best. */
+ code_block_size = 524288;
+ }
+ else if (local_code_size <= (1048576*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 1048576 is best. */
+ code_block_size = 1048576;
+ }
+ else if (local_code_size <= (2097152*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 2097152 is best. */
+ code_block_size = 2097152;
+ }
+ else if (local_code_size <= (4194304*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1)))
+ {
+ /* Block size of 4194304 is best. */
+ code_block_size = 4194304;
+ }
+ else
+ {
+ /* Just set block size to 32MB just to create an allocation error! */
+ code_block_size = 33554432;
+ }
+
+ /* Calculate the new code size. */
+ local_code_size = code_block_size*(TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1);
+
+ /* Determine if the code block size is greater than the current alignment. If so, use block size
+ as the alignment. */
+ if (code_block_size > local_code_alignment)
+ local_code_alignment = code_block_size;
+
+ }
+ else
+ {
+ /* Determine code block sizes. Minimize the alignment requirement.
+ There are 4 MPU code entries available. The following is how the code size
+ will be distributed:
+ 1. 1/4 of the largest power of two that is greater than or equal to code size.
+ 2. 1/4 of the largest power of two that is greater than or equal to code size.
+ 3. Largest power of 2 that fits in the remaining space.
+ 4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
+ local_code_alignment = _txm_power_of_two_block_size(local_code_size) >> 2;
+ code_size_accum = local_code_alignment + local_code_alignment;
+ code_size_accum = code_size_accum + (_txm_power_of_two_block_size(local_code_size - code_size_accum) >> 1);
+ code_size_accum = code_size_accum + _txm_power_of_two_block_size(local_code_size - code_size_accum);
+ local_code_size = code_size_accum;
+ }
+
+ /* Determine the best data block size, which in our case is the minimal alignment. */
+ if (local_data_size <= (32*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 32 is best. */
+ data_block_size = 32;
+ }
+ else if (local_data_size <= (64*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 64 is best. */
+ data_block_size = 64;
+ }
+ else if (local_data_size <= (128*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 128 is best. */
+ data_block_size = 128;
+ }
+ else if (local_data_size <= (256*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 256 is best. */
+ data_block_size = 256;
+ }
+ else if (local_data_size <= (512*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 512 is best. */
+ data_block_size = 512;
+ }
+ else if (local_data_size <= (1024*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 1024 is best. */
+ data_block_size = 1024;
+ }
+ else if (local_data_size <= (2048*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 2048 is best. */
+ data_block_size = 2048;
+ }
+ else if (local_data_size <= (4096*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 4096 is best. */
+ data_block_size = 4096;
+ }
+ else if (local_data_size <= (8192*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 8192 is best. */
+ data_block_size = 8192;
+ }
+ else if (local_data_size <= (16384*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 16384 is best. */
+ data_block_size = 16384;
+ }
+ else if (local_data_size <= (32768*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 32768 is best. */
+ data_block_size = 32768;
+ }
+ else if (local_data_size <= (65536*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 65536 is best. */
+ data_block_size = 65536;
+ }
+ else if (local_data_size <= (131072*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 131072 is best. */
+ data_block_size = 131072;
+ }
+ else if (local_data_size <= (262144*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 262144 is best. */
+ data_block_size = 262144;
+ }
+ else if (local_data_size <= (524288*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 524288 is best. */
+ data_block_size = 524288;
+ }
+ else if (local_data_size <= (1048576*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 1048576 is best. */
+ data_block_size = 1048576;
+ }
+ else if (local_data_size <= (2097152*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 2097152 is best. */
+ data_block_size = 2097152;
+ }
+ else if (local_data_size <= (4194304*TXM_MODULE_MANAGER_DATA_MPU_ENTRIES))
+ {
+ /* Block size of 4194304 is best. */
+ data_block_size = 4194304;
+ }
+ else
+ {
+ /* Just set data block size to 32MB just to create an allocation error! */
+ data_block_size = 33554432;
+ }
+
+ /* Calculate the new data size. */
+ data_size_accum = data_block_size;
+ while(data_size_accum < local_data_size)
+ {
+ data_size_accum += data_block_size;
+ }
+ local_data_size = data_size_accum;
+
+ /* Determine if the data block size is greater than the current alignment. If so, use block size
+ as the alignment. */
+ if (data_block_size > local_data_alignment)
+ {
+ local_data_alignment = data_block_size;
+ }
+
+ /* Return all the information to the caller. */
+ *code_size = local_code_size;
+ *code_alignment = local_code_alignment;
+ *data_size = local_data_size;
+ *data_alignment = local_data_alignment;
+
+#endif
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_external_memory_enable.c b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_external_memory_enable.c
new file mode 100644
index 00000000..5d499ff5
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_external_memory_enable.c
@@ -0,0 +1,297 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+#include "tx_api.h"
+#include "tx_mutex.h"
+#include "tx_queue.h"
+#include "tx_thread.h"
+#include "txm_module.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_external_memory_enable Cortex-Mx */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates an entry in the MPU table for a shared */
+/* memory space. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Module instance pointer */
+/* start_address Start address of memory */
+/* length Length of external memory */
+/* attributes Memory attributes (r/w) */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_mutex_get Get protection mutex */
+/* _tx_mutex_put Release protection mutex */
+/* _txm_power_of_two_block_size Round length to power of two */
+/* _txm_module_manager_mm_register_setup Reconfigure MPU registers */
+/* */
+/* CALLED BY */
+/* */
+/* Application code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 03-08-2023 Scott Larson Update defines, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_external_memory_enable(TXM_MODULE_INSTANCE *module_instance,
+ VOID *start_address,
+ ULONG length,
+ UINT attributes)
+{
+#ifdef TXM_MODULE_MANAGER_16_MPU
+ULONG block_size;
+ULONG region_size;
+ULONG srd_bits;
+ULONG size_register;
+ULONG address;
+ULONG shared_index;
+ULONG attributes_check = 0;
+
+ /* Determine if the module manager has not been initialized yet. */
+ if (_txm_module_manager_ready != TX_TRUE)
+ {
+ /* Module manager has not been initialized. */
+ return(TX_NOT_AVAILABLE);
+ }
+
+ /* Determine if the module is valid. */
+ if (module_instance == TX_NULL)
+ {
+ /* Invalid module pointer. */
+ return(TX_PTR_ERROR);
+ }
+
+ /* Get module manager protection mutex. */
+ _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
+
+ /* Determine if the module instance is valid. */
+ if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid module pointer. */
+ return(TX_PTR_ERROR);
+ }
+
+ /* Determine if the module instance is in the loaded state. */
+ if (module_instance -> txm_module_instance_state != TXM_MODULE_LOADED)
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return error if the module is not ready. */
+ return(TX_START_ERROR);
+ }
+
+ /* Determine if there are shared memory entries available. */
+ if(module_instance -> txm_module_instance_shared_memory_count >= TXM_MODULE_MANAGER_MPU_SHARED_ENTRIES)
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* No more entries available. */
+ return(TX_NO_MEMORY);
+ }
+
+ /* Start address and length must adhere to Cortex-M7 MPU.
+ The address must align with the block size. */
+
+ block_size = _txm_power_of_two_block_size(length);
+ address = (ULONG) start_address;
+ if(address != (address & ~(block_size - 1)))
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return alignment error. */
+ return(TXM_MODULE_ALIGNMENT_ERROR);
+ }
+
+ /* At this point, we have a valid address and block size.
+ Set up MPU registers. */
+
+ /* Pick up index into shared memory entries. */
+ shared_index = TXM_MODULE_MANAGER_MPU_SHARED_INDEX + module_instance -> txm_module_instance_shared_memory_count;
+
+ /* Save address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_address = address | shared_index | TXM_MPU_VALID_BIT;
+
+ /* Calculate the region size. */
+ region_size = _txm_module_manager_region_size_get(block_size);
+
+ /* Calculate the subregion bits. */
+ srd_bits = _txm_module_manager_calculate_srd_bits(block_size, length);
+
+ /* Generate SRD, size, and enable attributes. */
+ size_register = srd_bits | (region_size << 1) | TXM_ENABLE_REGION | TXM_MODULE_MPU_SHARED_ACCESS_CONTROL;
+
+ /* Check for optional write attribute. */
+ if(attributes & TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE)
+ {
+ attributes_check = TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT;
+ }
+
+ /* Save attribute-size register. */
+ module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_attribute_size = attributes_check | size_register;
+
+ /* Keep track of shared memory address and length in module instance. */
+ module_instance -> txm_module_instance_shared_memory_address[module_instance -> txm_module_instance_shared_memory_count] = address;
+ module_instance -> txm_module_instance_shared_memory_length[module_instance -> txm_module_instance_shared_memory_count] = length;
+
+ /* Increment counter. */
+ module_instance -> txm_module_instance_shared_memory_count++;
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return success. */
+ return(TX_SUCCESS);
+
+#else
+
+ULONG block_size;
+ULONG region_size;
+ULONG subregion_bits;
+ULONG address;
+UINT attributes_check = 0;
+TXM_MODULE_PREAMBLE *module_preamble;
+
+ /* Determine if the module manager has not been initialized yet. */
+ if (_txm_module_manager_ready != TX_TRUE)
+ {
+ /* Module manager has not been initialized. */
+ return(TX_NOT_AVAILABLE);
+ }
+
+ /* Determine if the module is valid. */
+ if (module_instance == TX_NULL)
+ {
+ /* Invalid module pointer. */
+ return(TX_PTR_ERROR);
+ }
+
+ /* Get module manager protection mutex. */
+ _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
+
+ /* Determine if the module instance is valid. */
+ if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Invalid module pointer. */
+ return(TX_PTR_ERROR);
+ }
+
+ /* Determine if the module instance is in the loaded state. */
+ if (module_instance -> txm_module_instance_state != TXM_MODULE_LOADED)
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return error if the module is not ready. */
+ return(TX_START_ERROR);
+ }
+
+ /* Check if preamble shared mem and mem protection property bits are set. */
+ module_preamble = module_instance -> txm_module_instance_preamble_ptr;
+ if((module_preamble -> txm_module_preamble_property_flags & (TXM_MODULE_MEMORY_PROTECTION | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS))
+ != (TXM_MODULE_MEMORY_PROTECTION | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS))
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return error if bit not set. */
+ return(TXM_MODULE_INVALID_PROPERTIES);
+ }
+
+ /* Start address and length must adhere to Cortex-M MPU.
+ The address must align with the block size. */
+
+ block_size = _txm_power_of_two_block_size(length);
+ address = (ULONG) start_address;
+ if(address != (address & ~(block_size - 1)))
+ {
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return alignment error. */
+ return(TXM_MODULE_ALIGNMENT_ERROR);
+ }
+
+ /* At this point, we have a valid address and block size.
+ Set up MPU registers. */
+ module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_SHARED_MPU_REGION].txm_module_mpu_region_address = address | TXM_MODULE_MANAGER_SHARED_MPU_REGION | TXM_MPU_VALID_BIT;
+
+ /* Calculate the region size. */
+ region_size = _txm_module_manager_region_size_get(block_size);
+ /* Calculate the subregion bits. */
+ subregion_bits = _txm_module_manager_calculate_srd_bits(block_size, length);
+
+ /* Check for valid attributes. */
+ if(attributes & TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE)
+ {
+ attributes_check = TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT;
+ }
+
+ /* Build register with attributes. */
+ module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_SHARED_MPU_REGION].txm_module_mpu_region_attribute_size = (region_size << 1) | subregion_bits | attributes_check | TXM_MODULE_MPU_SHARED_ACCESS_CONTROL | TXM_ENABLE_REGION;
+
+ /* Keep track of shared memory address and length in module instance. */
+ module_instance -> txm_module_instance_shared_memory_address = address;
+ module_instance -> txm_module_instance_shared_memory_length = length;
+
+ /* Recalculate MPU settings. */
+ _txm_module_manager_mm_register_setup(module_instance);
+
+ /* Release the protection mutex. */
+ _tx_mutex_put(&_txm_module_manager_mutex);
+
+ /* Return success. */
+ return(TX_SUCCESS);
+
+#endif
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_handler.c b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_handler.c
new file mode 100644
index 00000000..1032cbd6
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_handler.c
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "txm_module.h"
+
+
+/* Define the user's fault notification callback function pointer. This is
+ setup via the txm_module_manager_memory_fault_notify API. */
+
+VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *);
+
+
+/* Define a macro that can be used to allocate global variables useful to
+ store information about the last fault. This macro is defined in
+ txm_module_port.h and is usually populated in the assembly language
+ fault handling prior to the code calling _txm_module_manager_memory_fault_handler. */
+
+TXM_MODULE_MANAGER_FAULT_INFO
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_memory_fault_handler Cortex-Mx */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles a fault associated with a memory protected */
+/* module. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_terminate Terminate thread */
+/* */
+/* CALLED BY */
+/* */
+/* Fault handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+VOID _txm_module_manager_memory_fault_handler(VOID)
+{
+
+TXM_MODULE_INSTANCE *module_instance_ptr;
+TX_THREAD *thread_ptr;
+
+ /* Pickup the current thread. */
+ thread_ptr = _tx_thread_current_ptr;
+
+ /* Initialize the module instance pointer to NULL. */
+ module_instance_ptr = TX_NULL;
+
+ /* Is there a thread? */
+ if (thread_ptr)
+ {
+ /* Pickup the module instance. */
+ module_instance_ptr = thread_ptr -> tx_thread_module_instance_ptr;
+
+ /* Terminate the current thread. */
+ _tx_thread_terminate(_tx_thread_current_ptr);
+ }
+
+ /* Determine if there is a user memory fault notification callback. */
+ if (_txm_module_manager_fault_notify)
+ {
+ /* Yes, call the user's notification memory fault callback. */
+ (_txm_module_manager_fault_notify)(thread_ptr, module_instance_ptr);
+ }
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_notify.c b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_notify.c
new file mode 100644
index 00000000..65c6ca10
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_memory_fault_notify.c
@@ -0,0 +1,84 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "txm_module.h"
+
+
+/* Define the external user's fault notification callback function pointer. This is
+ setup via the txm_module_manager_memory_fault_notify API. */
+
+extern VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *);
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_memory_fault_notify Cortex-Mx */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers an application callback when/if a memory */
+/* fault occurs. The supplied thread is automatically terminated, but */
+/* any other threads in the same module may still execute. */
+/* */
+/* INPUT */
+/* */
+/* notify_function Memory fault notification */
+/* function, NULL disables. */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *))
+{
+ /* Setup notification function. */
+ _txm_module_manager_fault_notify = notify_function;
+
+ /* Return success. */
+ return(TX_SUCCESS);
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_mm_register_setup.c
new file mode 100644
index 00000000..a6b77473
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/common/module_manager/src/txm_module_manager_mm_register_setup.c
@@ -0,0 +1,860 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+#include "tx_api.h"
+#include "txm_module.h"
+
+#ifdef TXM_MODULE_MPU_DEFAULT
+const ULONG txm_module_default_mpu_registers[32] =
+ {
+ TXM_MODULE_MPU_DEFAULT_RBAR_0,
+ TXM_MODULE_MPU_DEFAULT_RASR_0,
+ TXM_MODULE_MPU_DEFAULT_RBAR_1,
+ TXM_MODULE_MPU_DEFAULT_RASR_1,
+ TXM_MODULE_MPU_DEFAULT_RBAR_2,
+ TXM_MODULE_MPU_DEFAULT_RASR_2,
+ TXM_MODULE_MPU_DEFAULT_RBAR_3,
+ TXM_MODULE_MPU_DEFAULT_RASR_3,
+ TXM_MODULE_MPU_DEFAULT_RBAR_4,
+ TXM_MODULE_MPU_DEFAULT_RASR_4,
+ TXM_MODULE_MPU_DEFAULT_RBAR_5,
+ TXM_MODULE_MPU_DEFAULT_RASR_5,
+ TXM_MODULE_MPU_DEFAULT_RBAR_6,
+ TXM_MODULE_MPU_DEFAULT_RASR_6,
+ TXM_MODULE_MPU_DEFAULT_RBAR_7,
+ TXM_MODULE_MPU_DEFAULT_RASR_7,
+ TXM_MODULE_MPU_DEFAULT_RBAR_8,
+ TXM_MODULE_MPU_DEFAULT_RASR_8,
+ TXM_MODULE_MPU_DEFAULT_RBAR_9,
+ TXM_MODULE_MPU_DEFAULT_RASR_9,
+ TXM_MODULE_MPU_DEFAULT_RBAR_10,
+ TXM_MODULE_MPU_DEFAULT_RASR_10,
+ TXM_MODULE_MPU_DEFAULT_RBAR_11,
+ TXM_MODULE_MPU_DEFAULT_RASR_11,
+ TXM_MODULE_MPU_DEFAULT_RBAR_12,
+ TXM_MODULE_MPU_DEFAULT_RASR_12,
+ TXM_MODULE_MPU_DEFAULT_RBAR_13,
+ TXM_MODULE_MPU_DEFAULT_RASR_13,
+ TXM_MODULE_MPU_DEFAULT_RBAR_14,
+ TXM_MODULE_MPU_DEFAULT_RASR_14,
+ TXM_MODULE_MPU_DEFAULT_RBAR_15,
+ TXM_MODULE_MPU_DEFAULT_RASR_15
+ };
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_region_size_get Cortex-Mx */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function converts the region size in bytes to the block size */
+/* for the Cortex-Mx MPU specification. */
+/* */
+/* INPUT */
+/* */
+/* block_size Size of the block in bytes */
+/* Must be a power of two */
+/* */
+/* OUTPUT */
+/* */
+/* MPU size specification */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_mm_register_setup */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 03-08-2023 Scott Larson Changed from lookup table to */
+/* calculation and check for */
+/* minumum block size, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+ULONG _txm_module_manager_region_size_get(ULONG block_size)
+{
+
+ULONG return_value = 5; /* 5 is the region size for 64 byte block. */
+
+ /* Check if at or below minumum block size. */
+ if (block_size <= 32)
+ {
+ /* Return minimum region size. */
+ return 0x04;
+ }
+
+ /* Remove some trailing zeros from block_size. */
+ block_size = block_size >> 6;
+
+ /* Increment return_value until block_size lsb is set. */
+ while((block_size & 1) == 0)
+ {
+ block_size = block_size >> 1;
+ return_value++;
+ }
+
+ return(return_value);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_calculate_srd_bits Cortex-Mx */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calculates the SRD bits that need to be set to */
+/* protect "length" bytes in a block. */
+/* */
+/* INPUT */
+/* */
+/* block_size Size of the block in bytes */
+/* length Actual length in bytes */
+/* */
+/* OUTPUT */
+/* */
+/* SRD bits to be OR'ed with region attribute register. */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_mm_register_setup */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+ULONG _txm_module_manager_calculate_srd_bits(ULONG block_size, ULONG length)
+{
+
+ULONG srd_bits = 0;
+UINT srd_bit_index;
+
+ /* length is smaller than block_size, set SRD bits if block_size is 256 or more. */
+ if((block_size >= 256) && (length < block_size))
+ {
+ /* Divide block_size by 8 by shifting right 3. Result is size of subregion. */
+ block_size = block_size >> 3;
+
+ /* Set SRD index into attribute register. */
+ srd_bit_index = 8;
+
+ /* If subregion overlaps length, move to the next subregion. */
+ while(length > block_size)
+ {
+ length = length - block_size;
+ srd_bit_index++;
+ }
+ /* Check for a portion of code remaining. */
+ if(length)
+ {
+ srd_bit_index++;
+ }
+
+ /* Set unused subregion bits. */
+ while(srd_bit_index < 16)
+ {
+ srd_bits = srd_bits | (0x1 << srd_bit_index);
+ srd_bit_index++;
+ }
+ }
+
+ return(srd_bits);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_mm_register_setup Cortex-Mx */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets up the MPU register definitions based on the */
+/* module's memory characteristics. */
+/* */
+/* Default MPU layout: */
+/* Entry Description */
+/* 0 Kernel mode entry */
+/* 1 Module code region */
+/* 2 Module code region */
+/* 3 Module code region */
+/* 4 Module code region [optional shared memory region] */
+/* 5 Module data region */
+/* 6 Module data region */
+/* 7 Module data region */
+/* */
+/* If TXM_MODULE_MANAGER_16_MPU is defined, there are 16 MPU slots. */
+/* MPU layout for the Cortex-M7: */
+/* Entry Description */
+/* 0 Kernel mode entry */
+/* 1 Module code region */
+/* 2 Module code region */
+/* 3 Module code region */
+/* 4 Module code region */
+/* 5 Module data region */
+/* 6 Module data region */
+/* 7 Module data region */
+/* 8 Module data region */
+/* 9 Module shared memory region */
+/* 10 Module shared memory region */
+/* 11 Module shared memory region */
+/* 12 User-defined region */
+/* 13 User-defined region */
+/* 14 User-defined region */
+/* 15 User-defined region */
+/* */
+/* */
+/* INPUT */
+/* */
+/* module_instance Pointer to module instance */
+/* */
+/* OUTPUT */
+/* */
+/* MPU specifications for module in module_instance */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_manager_region_size_get */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_thread_create */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 07-29-2022 Scott Larson Enable user defined regions, */
+/* resulting in version 6.1.12 */
+/* 03-08-2023 Scott Larson Initialize unused MPU region, */
+/* fix MPU settings for region */
+/* size less than 32 bytes, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance)
+{
+#ifdef TXM_MODULE_MANAGER_16_MPU
+
+ULONG code_address;
+ULONG code_size;
+ULONG data_address;
+ULONG data_size;
+ULONG start_stop_stack_size;
+ULONG callback_stack_size;
+ULONG block_size;
+ULONG region_size;
+ULONG srd_bits = 0;
+UINT mpu_table_index = 1;
+UINT i;
+
+
+ /* Setup the first MPU region for kernel mode entry. */
+ /* Set address register to user mode entry function address, which is guaranteed to be at least 32-byte aligned.
+ Mask address to proper range, region 0, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_address = ((ULONG) _txm_module_manager_user_mode_entry & 0xFFFFFFE0) | TXM_MPU_VALID_BIT;
+ /* Set the attributes, region size (32 bytes), and enable bit. */
+ module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_CODE_ACCESS_CONTROL | 0x08 | TXM_ENABLE_REGION;
+ /* End of kernel mode entry setup. */
+
+ /* Setup code protection. */
+
+ /* Pickup code starting address and actual size. */
+ code_address = (ULONG) module_instance -> txm_module_instance_code_start;
+ code_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_code_size;
+
+ /* Determine code block sizes. Minimize the alignment requirement.
+ There are 4 MPU code entries available. The following is how the code size
+ will be distributed:
+ 1. 1/4 of the largest power of two that is greater than or equal to code size.
+ 2. 1/4 of the largest power of two that is greater than or equal to code size.
+ 3. Largest power of 2 that fits in the remaining space.
+ 4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
+
+ /* Now loop through to setup MPU protection for the code area. */
+ for (i = 0; i < TXM_MODULE_MANAGER_MPU_CODE_ENTRIES; i++)
+ {
+ switch(i)
+ {
+ /* First two MPU blocks are 1/4 of the largest power of two
+ that is greater than or equal to code size. */
+ case 0:
+ {
+ block_size = _txm_power_of_two_block_size(code_size) >> 2;
+ break;
+ }
+ case 2:
+ {
+ /* Third MPU block is the largest power of 2 that fits within the remaining space. */
+ /* Subtract (block_size*2) from code_size to calculate remaining space. */
+ code_size = code_size - (block_size << 1);
+ block_size = _txm_power_of_two_block_size(code_size);
+
+ /* Minimum block size is 32. */
+ if(block_size > 32)
+ {
+ /* POW2 function result is divided by two to fit in the remaining space. */
+ block_size = block_size >> 1;
+ }
+ break;
+ }
+ case 3:
+ {
+ /* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
+ /* Calculate remaining space. */
+ if(code_size - block_size > code_size)
+ {
+ /* Case 2 covered the remaining code size. This region will not be used. */
+ block_size = 0;
+ }
+ else
+ {
+ code_size = code_size - block_size;
+ block_size = _txm_power_of_two_block_size(code_size);
+ srd_bits = _txm_module_manager_calculate_srd_bits(block_size, code_size);
+ }
+ break;
+ }
+ default:
+ {
+ /* Case 1 is the same as 0 - the block size was already calculated. */
+ break;
+ }
+ }
+
+ /* Build the base address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = (code_address & ~(block_size - 1)) | mpu_table_index | TXM_MPU_VALID_BIT;
+
+ /* Only configure attribute register if the block is valid. */
+ if(block_size)
+ {
+ /* Calculate the region size information. */
+ region_size = _txm_module_manager_region_size_get(block_size);
+
+ /* Build the attribute-size register with permissions, SRD, size, enable. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_CODE_ACCESS_CONTROL | srd_bits | (region_size << 1) | TXM_ENABLE_REGION;
+
+ /* Adjust the code address. */
+ code_address = code_address + block_size;
+ }
+ else
+ {
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = 0;
+ }
+
+ /* Increment MPU table index. */
+ mpu_table_index++;
+ }
+ /* End of code protection. */
+
+ /* Setup data protection. */
+
+ /* Reset SRD bitfield. */
+ srd_bits = 0;
+
+ /* Pickup data starting address and actual size. */
+ data_address = (ULONG) module_instance -> txm_module_instance_data_start;
+
+ /* Adjust the size of the module elements to be aligned to the default alignment. We do this
+ so that when we partition the allocated memory, we can simply place these regions right beside
+ each other without having to align their pointers. Note this only works when they all have
+ the same alignment. */
+
+ data_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_data_size;
+ start_stop_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_start_stop_stack_size;
+ callback_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_callback_stack_size;
+
+ data_size = ((data_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ start_stop_stack_size = ((start_stop_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ callback_stack_size = ((callback_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ /* Update the data size to include thread stacks. */
+ data_size = data_size + start_stop_stack_size + callback_stack_size;
+
+ /* Determine data block sizes. Minimize the alignment requirement.
+ There are 4 MPU data entries available. The following is how the data size
+ will be distributed:
+ 1. 1/4 of the largest power of two that is greater than or equal to data size.
+ 2. 1/4 of the largest power of two that is greater than or equal to data size.
+ 3. Largest power of 2 that fits in the remaining space.
+ 4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
+
+ /* Now loop through to setup MPU protection for the data area. */
+ for (i = 0; i < TXM_MODULE_MANAGER_MPU_DATA_ENTRIES; i++)
+ {
+ switch(i)
+ {
+ /* First two MPU blocks are 1/4 of the largest power of two
+ that is greater than or equal to data size. */
+ case 0:
+ {
+ block_size = _txm_power_of_two_block_size(data_size) >> 2;
+ break;
+ }
+ case 2:
+ {
+ /* Third MPU block is the largest power of 2 that fits within the remaining space. */
+ /* Subtract (block_size*2) from data_size to calculate remaining space. */
+ data_size = data_size - (block_size << 1);
+ block_size = _txm_power_of_two_block_size(data_size);
+
+ /* Minimum block size is 32. */
+ if(block_size > 32)
+ {
+ /* POW2 function result is divided by two to fit in the remaining space. */
+ block_size = block_size >> 1;
+ }
+ break;
+ }
+ case 3:
+ {
+ /* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
+ /* Calculate remaining space. */
+ if(data_size - block_size > data_size)
+ {
+ /* Case 2 covered the remaining data size. This region will not be used. */
+ block_size = 0;
+ }
+ else
+ {
+ data_size = data_size - block_size;
+ block_size = _txm_power_of_two_block_size(data_size);
+ srd_bits = _txm_module_manager_calculate_srd_bits(block_size, data_size);
+ }
+ break;
+ }
+ default:
+ {
+ /* Case 1 is the same as 0 - the block size was already calculated. */
+ break;
+ }
+ }
+
+ /* Build the base address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = (data_address & ~(block_size - 1)) | mpu_table_index | TXM_MPU_VALID_BIT;
+
+ /* Only configure attribute register if the block is valid. */
+ if(block_size)
+ {
+ /* Calculate the region size information. */
+ region_size = _txm_module_manager_region_size_get(block_size);
+
+ /* Build the attribute-size register with permissions, SRD, size, enable. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_DATA_ACCESS_CONTROL | srd_bits | (region_size << 1) | TXM_ENABLE_REGION;
+
+ /* Adjust the data address. */
+ data_address = data_address + block_size;
+ }
+ else
+ {
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = 0;
+ }
+
+ /* Increment MPU table index. */
+ mpu_table_index++;
+ }
+ /* End of data protection. */
+
+ /* Setup MPU for the shared regions. */
+ while (mpu_table_index < TXM_MODULE_MANAGER_MPU_USER_REGION_INDEX)
+ {
+ /* Build the base address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = mpu_table_index | TXM_MPU_VALID_BIT;
+
+ /* Increment MPU table index. */
+ mpu_table_index++;
+ }
+
+ /* Setup user-defined regions (12-15). */
+ module_instance -> txm_module_instance_mpu_registers[12].txm_module_mpu_region_address = TXM_MODULE_MPU_USER_DEFINED_RBAR_12;
+ module_instance -> txm_module_instance_mpu_registers[12].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_USER_DEFINED_RASR_12;
+ module_instance -> txm_module_instance_mpu_registers[13].txm_module_mpu_region_address = TXM_MODULE_MPU_USER_DEFINED_RBAR_13;
+ module_instance -> txm_module_instance_mpu_registers[13].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_USER_DEFINED_RASR_13;
+ module_instance -> txm_module_instance_mpu_registers[14].txm_module_mpu_region_address = TXM_MODULE_MPU_USER_DEFINED_RBAR_14;
+ module_instance -> txm_module_instance_mpu_registers[14].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_USER_DEFINED_RASR_14;
+ module_instance -> txm_module_instance_mpu_registers[15].txm_module_mpu_region_address = TXM_MODULE_MPU_USER_DEFINED_RBAR_15;
+ module_instance -> txm_module_instance_mpu_registers[15].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_USER_DEFINED_RASR_15;
+
+#else /* TXM_MODULE_MANAGER_16_MPU is not defined, only 8 MPU regions. */
+
+ULONG code_address;
+ULONG code_size;
+ULONG data_address;
+ULONG data_size;
+ULONG start_stop_stack_size;
+ULONG callback_stack_size;
+ULONG block_size;
+ULONG base_attribute_register;
+ULONG region_size;
+ULONG srd_bits = 0;
+UINT mpu_table_index = 1;
+UINT i;
+
+
+ /* Setup the first MPU region for kernel mode entry. */
+ /* Set address register to user mode entry function address, which is guaranteed to be at least 32-byte aligned.
+ Mask address to proper range, region 0, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_address = ((ULONG) _txm_module_manager_user_mode_entry & 0xFFFFFFE0) | TXM_MPU_VALID_BIT;
+ /* Set the attributes, region size (32 bytes), and enable bit. */
+ module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_CODE_ACCESS_CONTROL | 0x08 | TXM_ENABLE_REGION;
+ /* End of kernel mode entry setup. */
+
+ /* Setup code protection. */
+
+ /* Pickup code starting address and actual size. */
+ code_address = (ULONG) module_instance -> txm_module_instance_code_start;
+ code_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_code_size;
+
+ /* Check if shared memory was set up. If so, only 3 entries are available for
+ code protection. If not set up, 4 code entries are available. */
+ if(module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_SHARED_MPU_REGION].txm_module_mpu_region_address == 0)
+ {
+ /* Determine code block sizes. Minimize the alignment requirement.
+ There are 4 MPU code entries available. The following is how the code size
+ will be distributed:
+ 1. 1/4 of the largest power of two that is greater than or equal to code size.
+ 2. 1/4 of the largest power of two that is greater than or equal to code size.
+ 3. Largest power of 2 that fits in the remaining space.
+ 4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
+
+ /* Now loop through to setup MPU protection for the code area. */
+ for (i = 0; i < TXM_MODULE_MANAGER_CODE_MPU_ENTRIES; i++)
+ {
+ switch(i)
+ {
+ /* First two MPU blocks are 1/4 of the largest power of two
+ that is greater than or equal to code size. */
+ case 0:
+ {
+ block_size = _txm_power_of_two_block_size(code_size) >> 2;
+ break;
+ }
+ case 2:
+ {
+ /* Third MPU block is the largest power of 2 that fits within the remaining space. */
+ /* Subtract (block_size*2) from code_size to calculate remaining space. */
+ code_size = code_size - (block_size << 1);
+ block_size = _txm_power_of_two_block_size(code_size);
+
+ /* Minimum block size is 32. */
+ if(block_size > 32)
+ {
+ /* POW2 function result is divided by two to fit in the remaining space. */
+ block_size = block_size >> 1;
+ }
+ break;
+ }
+ case 3:
+ {
+ /* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
+ /* Calculate remaining space. */
+ if(code_size - block_size > code_size)
+ {
+ /* Case 2 covered the remaining code size. This region will not be used. */
+ block_size = 0;
+ }
+ else
+ {
+ code_size = code_size - block_size;
+ block_size = _txm_power_of_two_block_size(code_size);
+ srd_bits = _txm_module_manager_calculate_srd_bits(block_size, code_size);
+ }
+ break;
+ }
+ default:
+ {
+ /* Case 1 is the same as 0 - the block size was already calculated. */
+ break;
+ }
+ }
+
+ /* Build the base address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = (code_address & ~(block_size - 1)) | mpu_table_index | TXM_MPU_VALID_BIT;
+
+ /* Only configure attribute register if the block is valid. */
+ if(block_size)
+ {
+ /* Calculate the region size information. */
+ region_size = _txm_module_manager_region_size_get(block_size);
+
+ /* Build the attribute-size register with permissions, SRD, size, enable. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = TXM_MODULE_MPU_CODE_ACCESS_CONTROL | srd_bits | (region_size << 1) | TXM_ENABLE_REGION;
+
+ /* Adjust the code address. */
+ code_address = code_address + block_size;
+ }
+ else
+ {
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = 0;
+ }
+
+ /* Increment MPU table index. */
+ mpu_table_index++;
+ }
+ }
+
+ /* Only 3 code entries available. */
+ else
+ {
+ /* Calculate block size, one code entry taken up by shared memory. */
+ block_size = _txm_power_of_two_block_size(code_size / (TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1));
+
+ /* Calculate the region size and pre-shift it so we don't need to shift it multiple times in the for loop. */
+ region_size = _txm_module_manager_region_size_get(block_size) << 1;
+
+ /* Now loop through to setup MPU protection for the code area. */
+ for (i = 0; i < TXM_MODULE_MANAGER_CODE_MPU_ENTRIES - 1; i++)
+ {
+ /* Build the base address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = (code_address & ~(block_size - 1)) | mpu_table_index | TXM_MPU_VALID_BIT;
+
+ /* Check if SRD bits need to be set. */
+ if (code_size < block_size)
+ {
+ srd_bits = _txm_module_manager_calculate_srd_bits(block_size, code_size);
+ }
+
+ /* Build the base attribute register. */
+ base_attribute_register = region_size | srd_bits | TXM_MODULE_MPU_CODE_ACCESS_CONTROL;
+
+ /* Is there still some code? If so set the region enable bit. */
+ if (code_size)
+ {
+ /* Set the region enable bit. */
+ base_attribute_register |= TXM_ENABLE_REGION;
+ }
+
+ /* Setup the MPU Base Attribute Register. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = base_attribute_register;
+
+ /* Adjust the code address. */
+ code_address = code_address + block_size;
+
+ /* Decrement the code size. */
+ if (code_size > block_size)
+ {
+ code_size = code_size - block_size;
+ }
+ else
+ {
+ code_size = 0;
+ }
+
+ /* Increment MPU table index. */
+ mpu_table_index++;
+ }
+
+ /* Data protection is already set up so we can simply return here. */
+ return;
+ }
+
+ /* Setup values for data area. */
+ data_address = (ULONG) module_instance -> txm_module_instance_data_start;
+
+ /* Adjust the size of the module elements to be aligned to the default alignment. We do this
+ so that when we partition the allocated memory, we can simply place these regions right beside
+ each other without having to align their pointers. Note this only works when they all have
+ the same alignment. */
+
+ data_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_data_size;
+ start_stop_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_start_stop_stack_size;
+ callback_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_callback_stack_size;
+
+ data_size = ((data_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ start_stop_stack_size = ((start_stop_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ callback_stack_size = ((callback_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
+
+ /* Update the data size to include thread stacks. */
+ data_size = data_size + start_stop_stack_size + callback_stack_size;
+
+ block_size = _txm_power_of_two_block_size(data_size / TXM_MODULE_MANAGER_DATA_MPU_ENTRIES);
+
+ /* Reset SRD bitfield. */
+ srd_bits = 0;
+
+ /* Calculate the region size and pre-shift it so we don't need to shift it multiple times in the for loop. */
+ region_size = _txm_module_manager_region_size_get(block_size) << 1;
+
+ /* Now loop through to setup MPU protection for the data area. */
+ for (i = 0; i < TXM_MODULE_MANAGER_DATA_MPU_ENTRIES; i++)
+ {
+ /* Build the base address register with address, MPU region, set Valid bit. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = (data_address & ~(block_size - 1)) | mpu_table_index | TXM_MPU_VALID_BIT;
+
+ /* Check if SRD bits need to be set. */
+ if (data_size < block_size)
+ {
+ srd_bits = _txm_module_manager_calculate_srd_bits(block_size, data_size);
+ }
+
+ /* Build the attribute-size register with permissions, SRD, size. */
+ base_attribute_register = region_size | srd_bits | TXM_MODULE_MPU_DATA_ACCESS_CONTROL;
+
+ /* Is there still some data? If so set the region enable bit. */
+ if (data_size)
+ {
+ /* Set the region enable bit. */
+ base_attribute_register |= TXM_ENABLE_REGION;
+ }
+
+ /* Setup the MPU Base Attribute Register. */
+ module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attribute_size = base_attribute_register;
+
+ /* Adjust the data address. */
+ data_address = data_address + block_size;
+
+ /* Decrement the data size. */
+ if (data_size > block_size)
+ {
+ data_size = data_size - block_size;
+ }
+ else
+ {
+ data_size = 0;
+ }
+
+ /* Increment MPU table index. */
+ mpu_table_index++;
+ }
+
+#endif
+}
+
+#ifdef TXM_MODULE_MANAGER_16_MPU
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_inside_data_check Cortex-Mx */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks if the specified object is inside shared */
+/* memory. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Pointer to module instance */
+/* obj_ptr Pointer to the object */
+/* obj_size Size of the object */
+/* */
+/* OUTPUT */
+/* */
+/* Whether the object is inside the shared memory region. */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Module dispatch check functions */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size)
+{
+
+UINT shared_memory_index;
+UINT num_shared_memory_mpu_entries;
+ALIGN_TYPE shared_memory_address_start;
+ALIGN_TYPE shared_memory_address_end;
+
+ /* Check for overflow. */
+ if ((obj_ptr) > ((obj_ptr) + (obj_size)))
+ {
+ return(TX_FALSE);
+ }
+
+ /* Check if the object is inside the module data. */
+ if ((obj_ptr >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) &&
+ ((obj_ptr + obj_size) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_data_end + 1)))
+ {
+ return(TX_TRUE);
+ }
+
+ /* Check if the object is inside the shared memory. */
+ num_shared_memory_mpu_entries = module_instance -> txm_module_instance_shared_memory_count;
+ for (shared_memory_index = 0; shared_memory_index < num_shared_memory_mpu_entries; shared_memory_index++)
+ {
+
+ shared_memory_address_start = (ALIGN_TYPE) module_instance -> txm_module_instance_shared_memory_address[shared_memory_index];
+ shared_memory_address_end = shared_memory_address_start + module_instance -> txm_module_instance_shared_memory_length[shared_memory_index];
+
+ if ((obj_ptr >= (ALIGN_TYPE) shared_memory_address_start) &&
+ ((obj_ptr + obj_size) <= (ALIGN_TYPE) shared_memory_address_end))
+ {
+ return(TX_TRUE);
+ }
+ }
+
+ return(TX_FALSE);
+}
+#endif
diff --git a/ports_arch/ARMv7-M/threadx_modules/gnu/module_lib/src/txm_module_thread_shell_entry.c b/ports_arch/ARMv7-M/threadx_modules/gnu/module_lib/src/txm_module_thread_shell_entry.c
new file mode 100644
index 00000000..bdf4b94b
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/gnu/module_lib/src/txm_module_thread_shell_entry.c
@@ -0,0 +1,173 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TXM_MODULE
+#define TXM_MODULE
+#endif
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "txm_module.h"
+#include "tx_thread.h"
+
+/* Define the global module entry pointer from the start thread of the module. */
+
+TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
+
+
+/* Define the dispatch function pointer used in the module implementation. */
+
+ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
+
+
+/* Define the startup code that clears the uninitialized global data and sets up the
+ preset global variables. */
+
+extern VOID _gcc_setup(TXM_MODULE_INSTANCE *);
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_thread_shell_entry Cortex-Mx/GNU */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calls the specified entry function of the thread. It */
+/* also provides a place for the thread's entry function to return. */
+/* If the thread returns, this function places the thread in a */
+/* "COMPLETED" state. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to current thread */
+/* thread_info Pointer to thread entry info */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _gcc_setup cstartup initialization */
+/* thread_entry Thread's entry function */
+/* tx_thread_resume Resume the module callback thread */
+/* _txm_module_thread_system_suspend Module thread suspension routine */
+/* */
+/* CALLED BY */
+/* */
+/* Initial thread stack frame */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
+{
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+ VOID (*entry_exit_notify)(TX_THREAD *, UINT);
+#endif
+
+
+ /* Determine if this is the start thread. If so, we must prepare the module for
+ execution. If not, simply skip the C startup code. */
+ if (thread_info -> txm_module_thread_entry_info_start_thread)
+ {
+ /* Initialize the C environment. */
+ _gcc_setup(thread_info -> txm_module_thread_entry_info_code_base_address);
+
+ /* Save the entry info pointer, for later use. */
+ _txm_module_entry_info = thread_info;
+
+ /* Save the kernel function dispatch address. This is used to make all resident calls from
+ the module. */
+ _txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
+
+ /* Ensure that we have a valid pointer. */
+ while (!_txm_module_kernel_call_dispatcher)
+ {
+ /* Loop here, if an error is present getting the dispatch function pointer!
+ An error here typically indicates the resident portion of _tx_thread_schedule
+ is not supporting the trap to obtain the function pointer. */
+ }
+
+ /* Resume the module's callback thread, already created in the manager. */
+ _txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
+ }
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has been entered! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
+ }
+#endif
+
+ /* Call current thread's entry function. */
+ (thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
+
+ /* Suspend thread with a "completed" state. */
+
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine again. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual thread suspension routine. */
+ _txm_module_thread_system_suspend(thread_ptr);
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S
new file mode 100644
index 00000000..b6aa4849
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S
@@ -0,0 +1,687 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .global _tx_thread_current_ptr
+ .global _tx_thread_execute_ptr
+ .global _tx_timer_time_slice
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+ .global _tx_thread_preempt_disable
+ .global _txm_module_manager_memory_fault_handler
+ .global _txm_module_manager_memory_fault_info
+#ifdef TX_LOW_POWER
+ .global tx_low_power_enter
+ .global tx_low_power_exit
+#endif
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/GNU */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 01-31-2022 Scott Larson Fixed predefined macro name, */
+/* resulting in version 6.1.10 */
+/* 04-25-2022 Scott Larson Optimized MPU configuration, */
+/* added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 07-29-2022 Scott Larson Removed the code path to skip */
+/* MPU reloading, optional */
+/* default MPU settings, */
+/* resulting in version 6.1.12 */
+/* 10-31-2022 Scott Larson Added low power support, */
+/* resulting in version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .global _tx_thread_schedule
+ .thumb_func
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __ARM_FP
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable memory fault registers. */
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, =0x70000 // Enable Usage, Bus, and MemManage faults
+ STR r1, [r0] //
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+
+ /* Memory Exception Handler. */
+ .global MemManage_Handler
+ .global BusFault_Handler
+ .global UsageFault_Handler
+ .thumb_func
+MemManage_Handler:
+ .thumb_func
+BusFault_Handler:
+ .thumb_func
+UsageFault_Handler:
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+
+ /* Now pickup and store all the fault related information. */
+
+ LDR r12,=_txm_module_manager_memory_fault_info // Pickup fault info struct
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ STR r1, [r12, #0] // Save current thread pointer in fault info structure
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, [r0] // Pickup SHCSR
+ STR r1, [r12, #8] // Save SHCSR
+ LDR r0, =0xE000ED28 // Build CFSR address
+ LDR r1, [r0] // Pickup CFSR
+ STR r1, [r12, #12] // Save CFSR
+ LDR r0, =0xE000ED34 // Build MMFAR address
+ LDR r1, [r0] // Pickup MMFAR
+ STR r1, [r12, #16] // Save MMFAR
+ LDR r0, =0xE000ED38 // Build BFAR address
+ LDR r1, [r0] // Pickup BFAR
+ STR r1, [r12, #20] // Save BFAR
+ MRS r0, CONTROL // Pickup current CONTROL register
+ STR r0, [r12, #24] // Save CONTROL
+ MRS r1, PSP // Pickup thread stack pointer
+ STR r1, [r12, #28] // Save thread stack pointer
+ LDR r0, [r1] // Pickup saved r0
+ STR r0, [r12, #32] // Save r0
+ LDR r0, [r1, #4] // Pickup saved r1
+ STR r0, [r12, #36] // Save r1
+ STR r2, [r12, #40] // Save r2
+ STR r3, [r12, #44] // Save r3
+ STR r4, [r12, #48] // Save r4
+ STR r5, [r12, #52] // Save r5
+ STR r6, [r12, #56] // Save r6
+ STR r7, [r12, #60] // Save r7
+ STR r8, [r12, #64] // Save r8
+ STR r9, [r12, #68] // Save r9
+ STR r10,[r12, #72] // Save r10
+ STR r11,[r12, #76] // Save r11
+ LDR r0, [r1, #16] // Pickup saved r12
+ STR r0, [r12, #80] // Save r12
+ LDR r0, [r1, #20] // Pickup saved lr
+ STR r0, [r12, #84] // Save lr
+ LDR r0, [r1, #24] // Pickup instruction address at point of fault
+ STR r0, [r12, #4] // Save point of fault
+ LDR r0, [r1, #28] // Pickup xPSR
+ STR r0, [r12, #88] // Save xPSR
+
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED28 // Build the Memory Management Fault Status Register (MMFSR)
+ LDRB r1, [r0] // Pickup the MMFSR, with the following bit definitions:
+ // Bit 0 = 1 -> Instruction address violation
+ // Bit 1 = 1 -> Load/store address violation
+ // Bit 7 = 1 -> MMFAR is valid
+ STRB r1, [r0] // Clear the MMFSR
+
+#ifdef __ARM_FP
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Save FPCCR
+#endif
+
+ BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+ CPSID i // Disable interrupts
+ BL _tx_execution_thread_exit // Call the thread exit function
+ CPSIE i // Enable interrupts
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from MemManage_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif
+ MOV lr, #0xFFFFFFFD // Load exception return code
+ BX lr // Return from exception
+
+
+ /* Generic context PendSV handler. */
+
+ .global PendSV_Handler
+ .global __tx_PendSVHandler
+ .syntax unified
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBNZ r1, __tx_ts_restore // Yes, schedule it
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+__tx_ts_restore:
+
+ /* A thread is ready, make the current thread the new thread
+ and enable interrupts. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+
+ MRS r5, CONTROL // Pickup current CONTROL register
+ LDR r4, [r1, #0x98] // Pickup current user mode flag
+ BIC r5, r5, #1 // Clear the UNPRIV bit
+ ORR r4, r4, r5 // Build new CONTROL register
+ MSR CONTROL, r4 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r3, #0 // Build disable value
+ CPSID i // Disable interrupts
+ STR r3, [r0] // Disable MPU
+ LDR r0, [r1, #0x90] // Pickup the module instance pointer
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r0, default_mpu // Is this thread owned by a module? No, default MPU setup
+#else
+ CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
+#endif
+
+ LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r2, default_mpu // Is protection required for this module? No, default MPU setup
+#else
+ CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
+#endif
+ LDR r1, =0xE000ED9C // MPU_RBAR register address
+
+ // Use alias registers to quickly load MPU
+ ADD r0, r0, #100 // Build address of MPU register start in thread control block
+
+#ifdef TXM_MODULE_MPU_DEFAULT
+ B config_mpu // configure MPU for module
+default_mpu:
+ LDR r0, =txm_module_default_mpu_registers // default MPU configuration
+#endif
+
+config_mpu:
+ LDM r0!,{r2-r9} // Load MPU regions 0-3
+ STM r1,{r2-r9} // Store MPU regions 0-3
+ LDM r0!,{r2-r9} // Load MPU regions 4-7
+ STM r1,{r2-r9} // Store MPU regions 4-7
+#ifdef TXM_MODULE_MANAGER_16_MPU
+ LDM r0!,{r2-r9} // Load MPU regions 8-11
+ STM r1,{r2-r9} // Store MPU regions 8-11
+ // Regions 12-15 are reserved for the user to define.
+ LDM r0,{r2-r9} // Load MPU regions 12-15
+ STM r1,{r2-r9} // Store MPU regions 12-15
+#endif
+
+_tx_enable_mpu:
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r1, #5 // Build enable value with background region enabled
+ STR r1, [r0] // Enable MPU
+skip_mpu_setup:
+ CPSIE i // Enable interrupts
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+
+ /* SVC Handler. */
+
+ .global SVC_Handler
+ .global __tx_SVCallHandler
+ .syntax unified
+ .thumb_func
+SVC_Handler:
+ .thumb_func
+__tx_SVCallHandler:
+
+ MRS r0, PSP // Pickup the PSP stack
+ LDR r1, [r0, #24] // Pickup the point of interrupt
+ LDRB r2, [r1, #-2] // Pickup the SVC parameter
+
+ /* Determine which SVC trap we are processing */
+
+ CMP r2, #1 // Is it the entry into ThreadX?
+ BNE _tx_thread_user_return // No, return to user mode
+
+ /* At this point we have an SVC 1, which means we are entering
+ the kernel from a module thread with user mode selected. */
+
+ LDR r2, =_txm_module_priv // Load address of where we should have come from
+ CMP r1, r2 // Did we come from user_mode_entry?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came.
+
+ LDR r3, [r0, #20] // This is the saved LR
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ MOV r1, #0 // Build clear value
+ STR r1, [r2, #0x98] // Clear the current user mode selection for thread
+ STR r3, [r2, #0xA0] // Save the original LR in thread control block
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_enter
+
+ /* Switch to the module thread's kernel stack */
+ LDR r0, [r2, #0xA8] // Load the module kernel stack end
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r1, [r2, #0xA4] // Load the module kernel stack start
+ LDR r3, [r2, #0xAC] // Load the module kernel stack size
+ STR r1, [r2, #12] // Set stack start
+ STR r0, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+ MRS r3, PSP // Pickup thread stack pointer
+#ifdef __ARM_FP
+ TST lr, #0x10 // Test for extended module stack
+ ITT EQ
+ ORREQ r3, r3, #1 // If so, set LSB in thread stack pointer to indicate extended frame
+ ORREQ lr, lr, #0x10 // Set bit, return with standard frame
+#endif
+ STR r3, [r2, #0xB0] // Save thread stack pointer
+#ifdef __ARM_FP
+ BIC r3, #1 // Clear possibly OR'd bit
+#endif
+
+ /* Build kernel stack by copying thread stack two registers at a time */
+ ADD r3, r3, #32 // Start at bottom of hardware stack
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+
+ MSR PSP, r0 // Set kernel stack pointer
+
+_tx_skip_kernel_stack_enter:
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+_tx_thread_user_return:
+ LDR r2, =_txm_module_user_mode_exit // Load address of where we should have come from
+ CMP r1, r2 // Did we come from user_mode_exit?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+ STR r1, [r2, #0x98] // Set the current user mode selection for thread
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_exit
+
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r0, [r2, #0xB4] // Load the module thread stack start
+ LDR r1, [r2, #0xB8] // Load the module thread stack end
+ LDR r3, [r2, #0xBC] // Load the module thread stack size
+ STR r0, [r2, #12] // Set stack start
+ STR r1, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+#ifdef __ARM_FP
+ /* If lazy stacking is pending, check if it can be cleared.
+ if(LSPACT && tx_thread_module_stack_start < FPCAR && FPCAR < tx_thread_module_stack_end)
+ then clear LSPACT. */
+ LDR r3, =0xE000EF34 // Address of FPCCR
+ LDR r3, [r3] // Load FPCCR
+ TST r3, #1 // Check if LSPACT is set
+ BEQ _tx_no_lazy_clear // if clear, move on
+ LDR r1, =0xE000EF38 // Address of FPCAR
+ LDR r1, [r1] // Load FPCAR
+ LDR r0, [r2, #0xA4] // Load kernel stack start
+ CMP r1, r0 // If FPCAR < start, move on
+ BLO _tx_no_lazy_clear
+ LDR r0, [r2, #0xA8] // Load kernel stack end
+ CMP r0, r1 // If end < FPCAR, move on
+ BLO _tx_no_lazy_clear
+ BIC r3, #1 // Clear LSPACT
+ LDR r1, =0xE000EF34 // Address of FPCCR
+ STR r3, [r1] // Save updated FPCCR
+_tx_no_lazy_clear:
+#endif
+
+ LDR r0, [r2, #0xB0] // Load the module thread stack pointer
+ MRS r3, PSP // Pickup kernel stack pointer
+#ifdef __ARM_FP
+ TST r0, #1 // Is module stack extended?
+ ITTE NE // If so...
+ BICNE lr, #0x10 // Clear bit, return with extended frame
+ BICNE r0, #1 // Clear bit that indicates extended module frame
+ ORREQ lr, lr, #0x10 // Else set bit, return with standard frame
+#endif
+
+ /* Copy kernel hardware stack to module thread stack. */
+ LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
+ STM r0!, {r1-r2} // Insert r0, r1 into thread stack
+ LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
+ STM r0!, {r1-r2} // Insert r2, r3 into thread stack
+ LDM r3!, {r1-r2} // Get r12, lr from kernel stack
+ STM r0!, {r1-r2} // Insert r12, lr into thread stack
+ LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
+ STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
+ SUB r0, r0, #32 // Subtract 32 to get back to top of stack
+ MSR PSP, r0 // Set thread stack pointer
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+
+_tx_skip_kernel_stack_exit:
+ MRS r0, CONTROL // Pickup current CONTROL register
+ ORR r0, r0, r1 // OR in the user mode bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+
+ /* Kernel entry function from user mode. */
+
+ .global _txm_module_manager_kernel_dispatch
+ .align 5
+ .syntax unified
+// VOID _txm_module_manager_user_mode_entry(VOID)
+// {
+ .global _txm_module_manager_user_mode_entry
+ .thumb_func
+_txm_module_manager_user_mode_entry:
+ SVC 1 // Enter kernel
+_txm_module_priv:
+ /* At this point, we are out of user mode. The original LR has been saved in the
+ thread control block. Simply call the kernel dispatch function. */
+ BL _txm_module_manager_kernel_dispatch
+
+ /* Pickup the original LR value while still in privileged mode */
+ LDR r2, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r3, [r2] // Pickup current thread pointer
+ LDR lr, [r3, #0xA0] // Pickup saved LR from original call
+
+ SVC 2 // Exit kernel and return to user mode
+_txm_module_user_mode_exit:
+ BX lr // Return to the caller
+ NOP
+ NOP
+ NOP
+ NOP
+// }
+
+#ifdef __ARM_FP
+
+ .global tx_thread_fpu_enable
+ .thumb_func
+tx_thread_fpu_enable:
+ .global tx_thread_fpu_disable
+ .thumb_func
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/txm_module_manager_thread_stack_build.s b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/txm_module_manager_thread_stack_build.s
new file mode 100644
index 00000000..75c9b234
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/txm_module_manager_thread_stack_build.s
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+ .syntax unified
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_thread_stack_build Cortex-Mx/GNU */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* function_ptr Pointer to shell function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
+// {
+ .global _txm_module_manager_thread_stack_build
+ .thumb_func
+_txm_module_manager_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ lr Interrupted lr (lr at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r0, [r2, #36] // Store initial r0, which is the thread control block
+
+ LDR r3, [r0, #8] // Pickup thread entry info pointer,which is in the stack pointer position of the thread control block.
+ // It was setup in the txm_module_manager_thread_create function. It will be overwritten later in this
+ // function with the actual, initial stack pointer.
+ STR r3, [r2, #40] // Store initial r1, which is the module entry information.
+ LDR r3, [r3, #8] // Pickup data base register from the module information
+ STR r3, [r2, #24] // Store initial r9 (data base register)
+ MOV r3, #0 // Clear r3 again
+
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's control block
+ BX lr // Return to caller
+// }
diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_lib/src/txm_module_thread_shell_entry.c b/ports_arch/ARMv7-M/threadx_modules/iar/module_lib/src/txm_module_thread_shell_entry.c
new file mode 100644
index 00000000..4808f6a7
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_lib/src/txm_module_thread_shell_entry.c
@@ -0,0 +1,173 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifndef TXM_MODULE
+#define TXM_MODULE
+#endif
+
+#ifndef TX_SOURCE_CODE
+#define TX_SOURCE_CODE
+#endif
+
+
+/* Include necessary system files. */
+
+#include "txm_module.h"
+#include "tx_thread.h"
+
+/* Define the global module entry pointer from the start thread of the module. */
+
+TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
+
+
+/* Define the dispatch function pointer used in the module implementation. */
+
+ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
+
+
+/* Define the startup code that clears the uninitialized global data and sets up the
+ preset global variables. */
+
+extern VOID __iar_data_init3(VOID);
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_thread_shell_entry Cortex-Mx/IAR */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function calls the specified entry function of the thread. It */
+/* also provides a place for the thread's entry function to return. */
+/* If the thread returns, this function places the thread in a */
+/* "COMPLETED" state. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to current thread */
+/* thread_info Pointer to thread entry info */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* __iar_data_init3 cstartup initialization */
+/* thread_entry Thread's entry function */
+/* tx_thread_resume Resume the module callback thread */
+/* _txm_module_thread_system_suspend Module thread suspension routine */
+/* */
+/* CALLED BY */
+/* */
+/* Initial thread stack frame */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
+{
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+ VOID (*entry_exit_notify)(TX_THREAD *, UINT);
+#endif
+
+
+ /* Determine if this is the start thread. If so, we must prepare the module for
+ execution. If not, simply skip the C startup code. */
+ if (thread_info -> txm_module_thread_entry_info_start_thread)
+ {
+ /* Initialize the C environment. */
+ __iar_data_init3();
+
+ /* Save the entry info pointer, for later use. */
+ _txm_module_entry_info = thread_info;
+
+ /* Save the kernel function dispatch address. This is used to make all resident calls from
+ the module. */
+ _txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
+
+ /* Ensure that we have a valid pointer. */
+ while (!_txm_module_kernel_call_dispatcher)
+ {
+ /* Loop here, if an error is present getting the dispatch function pointer!
+ An error here typically indicates the resident portion of _tx_thread_schedule
+ is not supporting the trap to obtain the function pointer. */
+ }
+
+ /* Resume the module's callback thread, already created in the manager. */
+ _txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
+ }
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has been entered! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
+ }
+#endif
+
+ /* Call current thread's entry function. */
+ (thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
+
+ /* Suspend thread with a "completed" state. */
+
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+ /* Pickup the entry/exit application callback routine again. */
+ entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
+
+ /* Determine if an application callback routine is specified. */
+ if (entry_exit_notify != TX_NULL)
+ {
+
+ /* Yes, notify application that this thread has exited! */
+ (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
+ }
+#endif
+
+ /* Call actual thread suspension routine. */
+ _txm_module_thread_system_suspend(thread_ptr);
+
+#ifdef TX_SAFETY_CRITICAL
+
+ /* If we ever get here, raise safety critical exception. */
+ TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
+#endif
+}
diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c
new file mode 100644
index 00000000..dd719370
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c
@@ -0,0 +1,804 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** IAR Multithreaded Library Support */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Define IAR library for tools prior to version 8. */
+
+#if (__VER__ < 8000000)
+
+
+/* IAR version 7 and below. */
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/* This implementation requires that the following macros are defined in the
+ tx_port.h file and <yvals.h> is included with the following code segments:
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+ This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
+ application.
+
+ Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
+*/
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+
+#include <yvals.h>
+
+
+#if _MULTI_THREAD
+
+TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
+UINT __tx_iar_system_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_system_lock_no_mutexes;
+UINT __tx_iar_system_lock_internal_errors;
+UINT __tx_iar_system_lock_isr_caller;
+
+
+/* Define the TLS access function for the IAR library. */
+
+void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
+{
+
+char _DLIB_TLS_MEMORY *p = 0;
+
+ /* Is there a current thread? */
+ if (_tx_thread_current_ptr)
+ p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
+ else
+ p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
+ p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
+ return (void _DLIB_TLS_MEMORY *) p;
+}
+
+
+/* Define mutexes for IAR library. */
+
+void __iar_system_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_LOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_system_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_system_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_system_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+}
+
+
+#if _DLIB_FILE_DESCRIPTOR
+
+TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
+UINT __tx_iar_file_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_file_lock_no_mutexes;
+UINT __tx_iar_file_lock_internal_errors;
+UINT __tx_iar_file_lock_isr_caller;
+
+
+void __iar_file_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_FLOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_file_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_file_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_file_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+#endif /* _DLIB_FILE_DESCRIPTOR */
+
+#endif /* _MULTI_THREAD */
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#else /* IAR version 8 and above. */
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+/* This implementation requires that the following macros are defined in the
+ tx_port.h file and <yvals.h> is included with the following code segments:
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+void *_tx_iar_create_per_thread_tls_area(void);
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+void __iar_Initlocks(void);
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+ This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
+ application.
+
+ Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
+*/
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+
+#include <DLib_threads.h>
+
+
+void * __aeabi_read_tp();
+
+void* _tx_iar_create_per_thread_tls_area();
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+
+#pragma section="__iar_tls$$DATA"
+
+/* Define the TLS access function for the IAR library. */
+void * __aeabi_read_tp(void)
+{
+ void *p = 0;
+ TX_THREAD *thread_ptr = _tx_thread_current_ptr;
+ if (thread_ptr)
+ {
+ p = thread_ptr->tx_thread_iar_tls_pointer;
+ }
+ else
+ {
+ p = __section_begin("__iar_tls$$DATA");
+ }
+ return p;
+}
+
+/* Define the TLS creation and destruction to use malloc/free. */
+
+void* _tx_iar_create_per_thread_tls_area()
+{
+ UINT tls_size = __iar_tls_size();
+
+ /* Get memory for TLS. */
+ void *p = malloc(tls_size);
+
+ /* Initialize TLS-area and run constructors for objects in TLS */
+ __iar_tls_init(p);
+ return p;
+}
+
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
+{
+ /* Destroy objects living in TLS */
+ __call_thread_dtors();
+ free(tls_ptr);
+}
+
+#ifndef _MAX_LOCK
+#define _MAX_LOCK 4
+#endif
+
+static TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
+static UINT __tx_iar_system_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_system_lock_no_mutexes;
+UINT __tx_iar_system_lock_internal_errors;
+UINT __tx_iar_system_lock_isr_caller;
+
+
+/* Define mutexes for IAR library. */
+
+void __iar_system_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_LOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_system_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_system_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_system_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *m)
+{
+ if (*m)
+ {
+ UINT status;
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+ }
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *m)
+{
+ if (*m)
+ {
+ UINT status;
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+ }
+}
+
+
+#if _DLIB_FILE_DESCRIPTOR
+
+#include <stdio.h> /* Added to get access to FOPEN_MAX */
+#ifndef _MAX_FLOCK
+#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */
+#endif
+
+
+TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
+UINT __tx_iar_file_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_file_lock_no_mutexes;
+UINT __tx_iar_file_lock_internal_errors;
+UINT __tx_iar_file_lock_isr_caller;
+
+
+void __iar_file_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_FLOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_file_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_file_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_file_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+#endif /* _DLIB_FILE_DESCRIPTOR */
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#endif /* IAR version 8 and above. */
diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_misra.s b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_misra.s
new file mode 100644
index 00000000..ab3fef69
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_misra.s
@@ -0,0 +1,763 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ #define SHT_PROGBITS 0x1
+
+ EXTERN __aeabi_memset
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_interrupt_disable
+ EXTERN _tx_thread_interrupt_restore
+ EXTERN _tx_thread_stack_analyze
+ EXTERN _tx_thread_stack_error_handler
+ EXTERN _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ EXTERN _tx_trace_buffer_current_ptr
+ EXTERN _tx_trace_buffer_end_ptr
+ EXTERN _tx_trace_buffer_start_ptr
+ EXTERN _tx_trace_event_enable_bits
+ EXTERN _tx_trace_full_notify_function
+ EXTERN _tx_trace_header_ptr
+#endif
+
+ PUBLIC _tx_misra_always_true
+ PUBLIC _tx_misra_block_pool_to_uchar_pointer_convert
+ PUBLIC _tx_misra_byte_pool_to_uchar_pointer_convert
+ PUBLIC _tx_misra_char_to_uchar_pointer_convert
+ PUBLIC _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ PUBLIC _tx_misra_indirect_void_to_uchar_pointer_convert
+ PUBLIC _tx_misra_memset
+ PUBLIC _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_object_to_uchar_pointer_convert
+#endif
+ PUBLIC _tx_misra_pointer_to_ulong_convert
+ PUBLIC _tx_misra_status_get
+ PUBLIC _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_time_stamp_get
+#endif
+ PUBLIC _tx_misra_timer_indirect_to_void_pointer_convert
+ PUBLIC _tx_misra_timer_pointer_add
+ PUBLIC _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_trace_event_insert
+#endif
+ PUBLIC _tx_misra_uchar_pointer_add
+ PUBLIC _tx_misra_uchar_pointer_dif
+ PUBLIC _tx_misra_uchar_pointer_sub
+ PUBLIC _tx_misra_uchar_to_align_type_pointer_convert
+ PUBLIC _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_uchar_to_entry_pointer_convert
+ PUBLIC _tx_misra_uchar_to_header_pointer_convert
+#endif
+ PUBLIC _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ PUBLIC _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_uchar_to_object_pointer_convert
+#endif
+ PUBLIC _tx_misra_uchar_to_void_pointer_convert
+ PUBLIC _tx_misra_ulong_pointer_add
+ PUBLIC _tx_misra_ulong_pointer_dif
+ PUBLIC _tx_misra_ulong_pointer_sub
+ PUBLIC _tx_misra_ulong_to_pointer_convert
+ PUBLIC _tx_misra_ulong_to_thread_pointer_convert
+ PUBLIC _tx_misra_user_timer_pointer_get
+ PUBLIC _tx_misra_void_to_block_pool_pointer_convert
+ PUBLIC _tx_misra_void_to_byte_pool_pointer_convert
+ PUBLIC _tx_misra_void_to_event_flags_pointer_convert
+ PUBLIC _tx_misra_void_to_indirect_uchar_pointer_convert
+ PUBLIC _tx_misra_void_to_mutex_pointer_convert
+ PUBLIC _tx_misra_void_to_queue_pointer_convert
+ PUBLIC _tx_misra_void_to_semaphore_pointer_convert
+ PUBLIC _tx_misra_void_to_thread_pointer_convert
+ PUBLIC _tx_misra_void_to_uchar_pointer_convert
+ PUBLIC _tx_misra_void_to_ulong_pointer_convert
+ PUBLIC _tx_misra_ipsr_get
+ PUBLIC _tx_misra_control_get
+ PUBLIC _tx_misra_control_set
+#ifdef __ARMVFP__
+ PUBLIC _tx_misra_fpccr_get
+ PUBLIC _tx_misra_vfp_touch
+#endif
+
+ PUBLIC _tx_misra_event_flags_group_not_used
+ PUBLIC _tx_misra_event_flags_set_notify_not_used
+ PUBLIC _tx_misra_queue_not_used
+ PUBLIC _tx_misra_queue_send_notify_not_used
+ PUBLIC _tx_misra_semaphore_not_used
+ PUBLIC _tx_misra_semaphore_put_notify_not_used
+ PUBLIC _tx_misra_thread_entry_exit_notify_not_used
+ PUBLIC _tx_misra_thread_not_used
+
+#ifdef TX_MISRA_ENABLE
+ PUBLIC _tx_version_id
+
+ SECTION `.data`:DATA:REORDER:NOROOT(2)
+ DATA
+// 51 CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.1 MISRA C Compliant *";
+_tx_version_id:
+ DC8 43H, 6FH, 70H, 79H, 72H, 69H, 67H, 68H
+ DC8 74H, 20H, 28H, 63H, 29H, 20H, 31H, 39H
+ DC8 39H, 36H, 2DH, 32H, 30H, 31H, 38H, 20H
+ DC8 45H, 78H, 70H, 72H, 65H, 73H, 73H, 20H
+ DC8 4CH, 6FH, 67H, 69H, 63H, 20H, 49H, 6EH
+ DC8 63H, 2EH, 20H, 2AH, 20H, 54H, 68H, 72H
+ DC8 65H, 61H, 64H, 58H, 20H, 36H, 2EH, 31H
+ DC8 20H, 4DH, 49H, 53H, 52H, 41H, 20H, 43H
+ DC8 20H, 43H, 6FH, 6DH, 70H, 6CH, 69H, 61H
+ DC8 6EH, 74H, 20H, 2AH, 0
+ DC8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+#endif //TX_MISRA_ENABLE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N ??_tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N ??_tx_misra_message_copy_1
+??_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+??_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N ??_tx_misra_message_copy_2
+??_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N ??_tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR.N R2,??DataTable2 // 0x54485244
+ CMP R1,R2
+ BNE.N ??_tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N ??_tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+??_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N ??_tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N ??_tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N ??_tx_misra_thread_stack_check_3
+??_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+??_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N ??_tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+??_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,??DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R5,??DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R5,??DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,??DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N ??_tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N ??_tx_misra_trace_event_insert_2
+??_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N ??_tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N ??_tx_misra_trace_event_insert_2
+??_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+??_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,??DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N ??_tx_misra_trace_event_insert_4
+ LDR.N R0,??DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,??DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,??DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N ??_tx_misra_trace_event_insert_0
+??_tx_misra_trace_event_insert_4:
+ LDR.N R0,??DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+??_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_1:
+ DC32 _tx_trace_buffer_current_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_2:
+ DC32 _tx_trace_event_enable_bits
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_5:
+ DC32 _tx_trace_buffer_end_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_6:
+ DC32 _tx_trace_buffer_start_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_7:
+ DC32 _tx_trace_header_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_8:
+ DC32 _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2:
+ DC32 0x54485244
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_3:
+ DC32 _tx_thread_system_state
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_4:
+ DC32 _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARMVFP__
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+ DC32 0
+
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s
new file mode 100644
index 00000000..0e47d0d2
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s
@@ -0,0 +1,673 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_execute_ptr
+ EXTERN _tx_timer_time_slice
+ EXTERN _tx_execution_thread_enter
+ EXTERN _tx_execution_thread_exit
+ EXTERN _tx_thread_preempt_disable
+ EXTERN _txm_module_manager_memory_fault_handler
+ EXTERN _txm_module_manager_memory_fault_info
+ EXTERN txm_module_default_mpu_registers
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mx/IAR */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 04-25-2022 Scott Larson Optimized MPU configuration, */
+/* added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 07-29-2022 Scott Larson Removed the code path to skip */
+/* MPU reloading, optional */
+/* default MPU settings, */
+/* resulting in version 6.1.12 */
+/* 10-31-2022 Scott Larson Added low power support, */
+/* resulting in version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ PUBLIC _tx_thread_schedule
+_tx_thread_schedule:
+
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __ARMVFP__
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable memory fault registers. */
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, =0x70000 // Enable Usage, Bus, and MemManage faults
+ STR r1, [r0] //
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+
+ /* Memory Exception Handler. */
+
+ PUBLIC MemManage_Handler
+ PUBLIC BusFault_Handler
+ PUBLIC UsageFault_Handler
+MemManage_Handler:
+BusFault_Handler:
+UsageFault_Handler:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+
+ /* Now pickup and store all the fault related information. */
+
+ LDR r12,=_txm_module_manager_memory_fault_info // Pickup fault info struct
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ STR r1, [r12, #0] // Save current thread pointer in fault info structure
+ LDR r0, =0xE000ED24 // Build SHCSR address
+ LDR r1, [r0] // Pickup SHCSR
+ STR r1, [r12, #8] // Save SHCSR
+ LDR r0, =0xE000ED28 // Build CFSR address
+ LDR r1, [r0] // Pickup CFSR
+ STR r1, [r12, #12] // Save CFSR
+ LDR r0, =0xE000ED34 // Build MMFAR address
+ LDR r1, [r0] // Pickup MMFAR
+ STR r1, [r12, #16] // Save MMFAR
+ LDR r0, =0xE000ED38 // Build BFAR address
+ LDR r1, [r0] // Pickup BFAR
+ STR r1, [r12, #20] // Save BFAR
+ MRS r0, CONTROL // Pickup current CONTROL register
+ STR r0, [r12, #24] // Save CONTROL
+ MRS r1, PSP // Pickup thread stack pointer
+ STR r1, [r12, #28] // Save thread stack pointer
+ LDR r0, [r1] // Pickup saved r0
+ STR r0, [r12, #32] // Save r0
+ LDR r0, [r1, #4] // Pickup saved r1
+ STR r0, [r12, #36] // Save r1
+ STR r2, [r12, #40] // Save r2
+ STR r3, [r12, #44] // Save r3
+ STR r4, [r12, #48] // Save r4
+ STR r5, [r12, #52] // Save r5
+ STR r6, [r12, #56] // Save r6
+ STR r7, [r12, #60] // Save r7
+ STR r8, [r12, #64] // Save r8
+ STR r9, [r12, #68] // Save r9
+ STR r10,[r12, #72] // Save r10
+ STR r11,[r12, #76] // Save r11
+ LDR r0, [r1, #16] // Pickup saved r12
+ STR r0, [r12, #80] // Save r12
+ LDR r0, [r1, #20] // Pickup saved lr
+ STR r0, [r12, #84] // Save lr
+ LDR r0, [r1, #24] // Pickup instruction address at point of fault
+ STR r0, [r12, #4] // Save point of fault
+ LDR r0, [r1, #28] // Pickup xPSR
+ STR r0, [r12, #88] // Save xPSR
+
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED28 // Build the Memory Management Fault Status Register (MMFSR)
+ LDRB r1, [r0] // Pickup the MMFSR, with the following bit definitions:
+ // Bit 0 = 1 -> Instruction address violation
+ // Bit 1 = 1 -> Load/store address violation
+ // Bit 7 = 1 -> MMFAR is valid
+ STRB r1, [r0] // Clear the MMFSR
+
+#ifdef __ARMVFP__
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Store the value
+#endif
+
+ BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+ CPSID i // Disable interrupts
+ BL _tx_execution_thread_exit // Call the thread exit function
+ CPSIE i // Enable interrupts
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from MemManage_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif
+ MOV lr, #0xFFFFFFFD // Load exception return code
+ BX lr // Return from exception
+
+
+ /* Generic context PendSV handler. */
+
+ PUBLIC PendSV_Handler
+ PUBLIC __tx_PendSVHandler
+PendSV_Handler:
+__tx_PendSVHandler:
+
+ /* Get current thread value and new thread pointer. */
+
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARMVFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ STR r12, [r1, #8] // Save the thread stack pointer
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBNZ r1, __tx_ts_restore // Yes, schedule it
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+__tx_ts_restore:
+
+ /* A thread is ready, make the current thread the new thread
+ and enable interrupts. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+ /* Restore the thread context and PSP. */
+
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+
+ MRS r5, CONTROL // Pickup current CONTROL register
+ LDR r4, [r1, #0x98] // Pickup current user mode flag
+ BIC r5, r5, #1 // Clear the UNPRIV bit
+ ORR r4, r4, r5 // Build new CONTROL register
+ MSR CONTROL, r4 // Setup new CONTROL register
+
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r3, #0 // Build disable value
+ CPSID i // Disable interrupts
+ STR r3, [r0] // Disable MPU
+ LDR r0, [r1, #0x90] // Pickup the module instance pointer
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r0, default_mpu // Is this thread owned by a module? No, default MPU setup
+#else
+ CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
+#endif
+
+ LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
+#ifdef TXM_MODULE_MPU_DEFAULT
+ CBZ r2, default_mpu // Is protection required for this module? No, default MPU setup
+#else
+ CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
+#endif
+ LDR r1, =0xE000ED9C // MPU_RBAR register address
+
+ // Use alias registers to quickly load MPU
+ ADD r0, r0, #100 // Build address of MPU register start in thread control block
+
+#ifdef TXM_MODULE_MPU_DEFAULT
+ B config_mpu // configure MPU for module
+default_mpu:
+ LDR r0, =txm_module_default_mpu_registers // default MPU configuration
+#endif
+
+config_mpu:
+ LDM r0!,{r2-r9} // Load MPU regions 0-3
+ STM r1,{r2-r9} // Store MPU regions 0-3
+ LDM r0!,{r2-r9} // Load MPU regions 4-7
+ STM r1,{r2-r9} // Store MPU regions 4-7
+#ifdef TXM_MODULE_MANAGER_16_MPU
+ LDM r0!,{r2-r9} // Load MPU regions 8-11
+ STM r1,{r2-r9} // Store MPU regions 8-11
+ // Regions 12-15 are reserved for the user to define.
+ LDM r0,{r2-r9} // Load MPU regions 12-15
+ STM r1,{r2-r9} // Store MPU regions 12-15
+#endif
+
+_tx_enable_mpu:
+ LDR r0, =0xE000ED94 // Build MPU control reg address
+ MOV r1, #5 // Build enable value with background region enabled
+ STR r1, [r0] // Enable MPU
+skip_mpu_setup:
+ CPSIE i // Enable interrupts
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARMVFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ /* Return to thread. */
+
+ BX lr // Return to thread!
+
+
+ /* SVC Handler. */
+
+ PUBLIC SVC_Handler
+ PUBLIC __tx_SVCallHandler
+SVC_Handler:
+__tx_SVCallHandler:
+
+ MRS r0, PSP // Pickup the PSP stack
+ LDR r1, [r0, #24] // Pickup the point of interrupt
+ LDRB r2, [r1, #-2] // Pickup the SVC parameter
+
+ /* Determine which SVC trap we are processing */
+
+ CMP r2, #1 // Is it the entry into ThreadX?
+ BNE _tx_thread_user_return // No, return to user mode
+
+ /* At this point we have an SVC 1, which means we are entering
+ the kernel from a module thread with user mode selected. */
+
+ LDR r2, =_txm_module_priv-1 // Load address of where we should have come from
+ // Subtract 1 because of THUMB mode.
+ CMP r1, r2 // Did we come from user_mode_entry?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came.
+
+ LDR r3, [r0, #20] // This is the saved LR
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ MOV r1, #0 // Build clear value
+ STR r1, [r2, #0x98] // Clear the current user mode selection for thread
+ STR r3, [r2, #0xA0] // Save the original LR in thread control block
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_enter
+
+ /* Switch to the module thread's kernel stack */
+ LDR r0, [r2, #0xA8] // Load the module kernel stack end
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r1, [r2, #0xA4] // Load the module kernel stack start
+ LDR r3, [r2, #0xAC] // Load the module kernel stack size
+ STR r1, [r2, #12] // Set stack start
+ STR r0, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+ MRS r3, PSP // Pickup thread stack pointer
+#ifdef __ARMVFP__
+ TST lr, #0x10 // Test for extended module stack
+ ITT EQ
+ ORREQ r3, r3, #1 // If so, set LSB in thread stack pointer to indicate extended frame
+ ORREQ lr, lr, #0x10 // Set bit, return with standard frame
+#endif
+ STR r3, [r2, #0xB0] // Save thread stack pointer
+#ifdef __ARMVFP__
+ BIC r3, #1 // Clear possibly OR'd bit
+#endif
+
+ /* Build kernel stack by copying thread stack two registers at a time */
+ ADD r3, r3, #32 // Start at bottom of hardware stack
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+ LDMDB r3!, {r1-r2}
+ STMDB r0!, {r1-r2}
+
+ MSR PSP, r0 // Set kernel stack pointer
+
+_tx_skip_kernel_stack_enter:
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #1 // Clear the UNPRIV bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+_tx_thread_user_return:
+ LDR r2, =_txm_module_user_mode_exit-1 // Load address of where we should have come from
+ // Subtract 1 because of THUMB mode.
+ CMP r1, r2 // Did we come from user_mode_exit?
+ IT NE // If no (not equal), then...
+ BXNE lr // return from where we came
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+ STR r1, [r2, #0x98] // Set the current user mode selection for thread
+
+ /* If there is memory protection, use kernel stack */
+ LDR r0, [r2, #0x90] // Load the module instance ptr
+ LDR r0, [r0, #0x0C] // Load the module property flags
+ TST r0, #2 // Check if memory protected
+ BEQ _tx_skip_kernel_stack_exit
+
+#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
+ LDR r0, [r2, #0xB4] // Load the module thread stack start
+ LDR r1, [r2, #0xB8] // Load the module thread stack end
+ LDR r3, [r2, #0xBC] // Load the module thread stack size
+ STR r0, [r2, #12] // Set stack start
+ STR r1, [r2, #16] // Set stack end
+ STR r3, [r2, #20] // Set stack size
+#endif
+
+#ifdef __ARMVFP__
+ /* If lazy stacking is pending, check if it can be cleared.
+ if(LSPACT && tx_thread_module_stack_start < FPCAR && FPCAR < tx_thread_module_stack_end)
+ then clear LSPACT. */
+ LDR r3, =0xE000EF34 // Address of FPCCR
+ LDR r3, [r3] // Load FPCCR
+ TST r3, #1 // Check if LSPACT is set
+ BEQ _tx_no_lazy_clear // if clear, move on
+ LDR r1, =0xE000EF38 // Address of FPCAR
+ LDR r1, [r1] // Load FPCAR
+ LDR r0, [r2, #0xA4] // Load kernel stack start
+ CMP r1, r0 // If FPCAR < start, move on
+ BLO _tx_no_lazy_clear
+ LDR r0, [r2, #0xA8] // Load kernel stack end
+ CMP r0, r1 // If end < FPCAR, move on
+ BLO _tx_no_lazy_clear
+ BIC r3, #1 // Clear LSPACT
+ LDR r1, =0xE000EF34 // Address of FPCCR
+ STR r3, [r1] // Save updated FPCCR
+_tx_no_lazy_clear:
+#endif
+
+ LDR r0, [r2, #0xB0] // Load the module thread stack pointer
+ MRS r3, PSP // Pickup kernel stack pointer
+#ifdef __ARMVFP__
+ TST r0, #1 // Is module stack extended?
+ ITTE NE // If so...
+ BICNE lr, #0x10 // Clear bit, return with extended frame
+ BICNE r0, #1 // Clear bit that indicates extended module frame
+ ORREQ lr, lr, #0x10 // Else set bit, return with standard frame
+#endif
+
+ /* Copy kernel hardware stack to module thread stack. */
+ LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
+ STM r0!, {r1-r2} // Insert r0, r1 into thread stack
+ LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
+ STM r0!, {r1-r2} // Insert r2, r3 into thread stack
+ LDM r3!, {r1-r2} // Get r12, lr from kernel stack
+ STM r0!, {r1-r2} // Insert r12, lr into thread stack
+ LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
+ STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
+ SUB r0, r0, #32 // Subtract 32 to get back to top of stack
+ MSR PSP, r0 // Set thread stack pointer
+
+ LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, [r1] // Pickup current thread pointer
+ LDR r1, [r2, #0x9C] // Pick up user mode
+
+_tx_skip_kernel_stack_exit:
+ MRS r0, CONTROL // Pickup current CONTROL register
+ ORR r0, r0, r1 // OR in the user mode bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+ BX lr // Return to thread
+
+
+ /* Kernel entry function from user mode. */
+
+ EXTERN _txm_module_manager_kernel_dispatch
+ SECTION `.text`:CODE:NOROOT(5)
+ THUMB
+ ALIGNROM 5
+// VOID _txm_module_manager_user_mode_entry(VOID)
+// {
+ PUBLIC _txm_module_manager_user_mode_entry
+_txm_module_manager_user_mode_entry:
+ SVC 1 // Enter kernel
+_txm_module_priv:
+ /* At this point, we are out of user mode. The original LR has been saved in the
+ thread control block. Simply call the kernel dispatch function. */
+ BL _txm_module_manager_kernel_dispatch
+
+ /* Pickup the original LR value while still in privileged mode */
+ LDR r2, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r3, [r2] // Pickup current thread pointer
+ LDR lr, [r3, #0xA0] // Pickup saved LR from original call
+
+ SVC 2 // Exit kernel and return to user mode
+_txm_module_user_mode_exit:
+ BX lr // Return to the caller
+ NOP
+ NOP
+ NOP
+ NOP
+// }
+
+#ifdef __ARMVFP__
+
+ PUBLIC tx_thread_fpu_enable
+tx_thread_fpu_enable:
+ PUBLIC tx_thread_fpu_disable
+tx_thread_fpu_disable:
+
+ /* Automatic VPF logic is supported, this function is present only for
+ backward compatibility purposes and therefore simply returns. */
+
+ BX LR // Return to caller
+
+#endif
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/txm_module_manager_thread_stack_build.s b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/txm_module_manager_thread_stack_build.s
new file mode 100644
index 00000000..bb691440
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/txm_module_manager_thread_stack_build.s
@@ -0,0 +1,138 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module Manager */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_thread_stack_build Cortex-Mx/IAR */
+/* 6.1.9 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* function_ptr Pointer to shell function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* */
+/**************************************************************************/
+// VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
+// {
+ PUBLIC _txm_module_manager_thread_stack_build
+_txm_module_manager_thread_stack_build:
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ lr Interrupted lr (lr at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame
+ SUB r2, r2, #68 // Subtract frame size
+ LDR r3, =0xFFFFFFFD // Build initial LR value
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r0, [r2, #36] // Store initial r0, which is the thread control block
+
+ LDR r3, [r0, #8] // Pickup thread entry info pointer,which is in the stack pointer position of the thread control block.
+ // It was setup in the txm_module_manager_thread_create function. It will be overwritten later in this
+ // function with the actual, initial stack pointer.
+ STR r3, [r2, #40] // Store initial r1, which is the module entry information.
+ LDR r3, [r3, #8] // Pickup data base register from the module information
+ STR r3, [r2, #24] // Store initial r9 (data base register)
+ MOV r3, #0 // Clear r3 again
+
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's control block
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h b/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h
new file mode 100644
index 00000000..368b91d1
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h
@@ -0,0 +1,732 @@
+/**************************************************************************/
+/* */
+/* 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 Cortex-Mx */
+/* 6.2.0 */
+/* */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
+/* the ARMv7-M architecture and compilers into one common file. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 04-25-2022 Scott Larson Modified comments and added */
+/* volatile to registers, */
+/* resulting in version 6.1.11 */
+/* */
+/**************************************************************************/
+
+#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 /* TX_INCLUDE_USER_DEFINE_FILE */
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __ICCARM__
+#include <intrinsics.h> /* IAR Intrinsics */
+#define __asm__ __asm /* Define to make all inline asm look similar */
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+#endif /* __ICCARM__ */
+
+#ifdef __ghs__
+#include <arm_ghs.h>
+#include "tx_ghs.h"
+#endif /* __ghs__ */
+
+
+#if !defined(__GNUC__) && !defined(__CC_ARM)
+#define __get_control_value __get_CONTROL
+#define __set_control_value __set_CONTROL
+#endif
+
+#ifndef __GNUC__
+#define __get_ipsr_value __get_IPSR
+#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 unsigned long long ULONG64;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#define ULONG64_DEFINED
+
+/* 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 200 /* 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
+
+/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts.
+If using BASEPRI is desired, define the following two symbols for both c and assembly files:
+TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK.
+TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask.
+Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run.
+*/
+
+/* Define various constants for the ThreadX Cortex-M port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* 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 *((volatile ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
+#endif
+#else
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#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. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* 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. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#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
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_module_instance_ptr; \
+ VOID *tx_thread_module_entry_info_ptr; \
+ ULONG tx_thread_module_current_user_mode; \
+ ULONG tx_thread_module_user_mode; \
+ ULONG tx_thread_module_saved_lr; \
+ VOID *tx_thread_module_kernel_stack_start; \
+ VOID *tx_thread_module_kernel_stack_end; \
+ ULONG tx_thread_module_kernel_stack_size; \
+ VOID *tx_thread_module_stack_ptr; \
+ VOID *tx_thread_module_stack_start; \
+ VOID *tx_thread_module_stack_end; \
+ ULONG tx_thread_module_stack_size; \
+ VOID *tx_thread_module_reserved; \
+ VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_module_instance_ptr; \
+ VOID *tx_thread_module_entry_info_ptr; \
+ ULONG tx_thread_module_current_user_mode; \
+ ULONG tx_thread_module_user_mode; \
+ ULONG tx_thread_module_saved_lr; \
+ VOID *tx_thread_module_kernel_stack_start; \
+ VOID *tx_thread_module_kernel_stack_end; \
+ ULONG tx_thread_module_kernel_stack_size; \
+ VOID *tx_thread_module_stack_ptr; \
+ VOID *tx_thread_module_stack_start; \
+ VOID *tx_thread_module_stack_end; \
+ ULONG tx_thread_module_stack_size; \
+ VOID *tx_thread_module_reserved;
+#endif
+#ifndef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+#define TX_THREAD_EXTENSION_3
+#else
+#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
+ unsigned long long tx_thread_execution_time_last_start;
+#endif
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \
+ VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
+
+#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \
+ VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
+
+#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \
+ VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
+
+#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \
+ VOID (*tx_timer_module_expiration_function)(ULONG id);
+
+
+/* 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. */
+
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#if (__VER__ < 8000000)
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
+#else
+void *_tx_iar_create_per_thread_tls_area(void);
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+void __iar_Initlocks(void);
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
+#endif
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
+
+#ifdef TX_MISRA_ENABLE
+
+ULONG _tx_misra_control_get(void);
+void _tx_misra_control_set(ULONG value);
+ULONG _tx_misra_fpccr_get(void);
+void _tx_misra_vfp_touch(void);
+
+#else /* TX_MISRA_ENABLE not defined */
+
+/* Define some helper functions (these are intrinsics in some compilers). */
+#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
+
+__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
+{
+ULONG control_value;
+
+ __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
+ return(control_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
+{
+ __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
+}
+
+#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
+
+#elif defined(__CC_ARM) /* ARM Compiler 5 */
+
+__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
+{
+ULONG control_value;
+
+ __asm volatile ("MRS control_value,CONTROL");
+ return(control_value);
+}
+
+__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
+{
+ __asm__ volatile ("MSR CONTROL,control_value");
+}
+/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
+void _tx_vfp_access(void);
+#define TX_VFP_TOUCH() _tx_vfp_access();
+
+#elif defined(__ICCARM__) /* IAR */
+#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
+#endif /* Helper functions for different compilers */
+
+#endif /* TX_MISRA_ENABLE */
+
+
+/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
+ in order to ensure no lazy stacking will occur. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control_value(_tx_vfp_state); \
+ }
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ }
+
+#endif
+
+/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
+ If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
+ this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
+ the lazy FPU save, then restore the CONTROL.FPCA state. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control_value(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ TX_VFP_TOUCH(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = __get_control_value(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ __set_control_value(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#else
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = _tx_misra_fpccr_get(); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ _tx_misra_vfp_touch(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#endif
+
+#else /* No VFP in use */
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
+
+
+/* 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 the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+#ifdef __CC_ARM /* ARM Compiler 5 */
+
+register unsigned int _ipsr __asm("ipsr");
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
+
+#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
+{
+unsigned int ipsr_value;
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
+
+#elif defined(__ICCARM__) /* IAR */
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
+
+#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
+
+#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif /* TX_MISRA_ENABLE */
+#endif /* TX_THREAD_GET_SYSTEM_STATE */
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
+ for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
+ zero after initialization for Cortex-M ports. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
+#ifdef __ICCARM__ /* IAR Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
+#elif defined(__CC_ARM) /* AC5 Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
+#elif defined(__GNUC__) /* GCC and AC6 Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
+ __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
+#else
+#error "Compiler not supported."
+#endif
+
+
+
+/* Define the interrupt disable/restore macros for each compiler. */
+
+#if defined(__GNUC__) || defined(__ICCARM__)
+
+/*** GCC/AC6 and IAR ***/
+
+__attribute__( ( always_inline ) ) static inline UINT __get_interrupt_posture(void)
+{
+UINT posture;
+#ifdef TX_PORT_USE_BASEPRI
+ __asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
+#else
+ __asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
+#endif
+ return(posture);
+}
+
+#ifdef TX_PORT_USE_BASEPRI
+__attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value)
+{
+ __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
+}
+#else
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+ __asm__ volatile ("CPSIE i": : : "memory");
+}
+#endif
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT int_posture)
+{
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(int_posture);
+#else
+ __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
+#endif
+}
+
+__attribute__( ( always_inline ) ) static inline UINT __disable_interrupts(void)
+{
+UINT int_posture;
+
+ int_posture = __get_interrupt_posture();
+
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(TX_PORT_BASEPRI);
+#else
+ __asm__ volatile ("CPSID i" : : : "memory");
+#endif
+ return(int_posture);
+}
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+UINT interrupt_save;
+
+ /* Set PendSV to invoke ThreadX scheduler. */
+ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (__get_ipsr_value() == 0)
+ {
+ interrupt_save = __get_interrupt_posture();
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(0);
+#else
+ __enable_interrupts();
+#endif
+ __restore_interrupt(interrupt_save);
+ }
+}
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupt(interrupt_save);
+
+/*** End GCC/AC6 and IAR ***/
+
+#elif defined(__CC_ARM)
+
+/*** AC5 ***/
+
+static __inline unsigned int __get_interrupt_posture(void)
+{
+unsigned int posture;
+#ifdef TX_PORT_USE_BASEPRI
+ __asm__ volatile ("MRS #posture, BASEPRI");
+#else
+ __asm__ volatile ("MRS #posture, PRIMASK");
+#endif
+ return(posture);
+}
+
+#ifdef TX_PORT_USE_BASEPRI
+static __inline void __set_basepri_value(unsigned int basepri_value)
+{
+ __asm__ volatile ("MSR BASEPRI, #basepri_value");
+}
+#endif
+
+static __inline unsigned int __disable_interrupts(void)
+{
+unsigned int int_posture;
+
+ int_posture = __get_interrupt_posture();
+
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(TX_PORT_BASEPRI);
+#else
+ __asm__ volatile ("CPSID i");
+#endif
+ return(int_posture);
+}
+
+static __inline void __restore_interrupt(unsigned int int_posture)
+{
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(int_posture);
+#else
+ __asm__ volatile ("MSR PRIMASK, #int_posture");
+#endif
+}
+
+static void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
+
+ /* Set PendSV to invoke ThreadX scheduler. */
+ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (_ipsr == 0)
+ {
+#ifdef TX_PORT_USE_BASEPRI
+ interrupt_save = __get_interrupt_posture();
+ __set_basepri_value(0);
+ __set_basepri_value(interrupt_save);
+#else
+ interrupt_save = __disable_irq();
+ __enable_irq();
+ if (interrupt_save != 0)
+ __disable_irq();
+#endif
+ }
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupt(interrupt_save);
+
+/*** End AC5 ***/
+
+#endif /* Interrupt disable/restore macros for each compiler. */
+
+/* Redefine _tx_thread_system_return for improved performance. */
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+#else /* TX_DISABLE_INLINE is defined */
+
+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);
+#endif /* TX_DISABLE_INLINE */
+
+
+/* Define FPU extension for the Cortex-M. Each is assumed to be called in the context of the executing
+ thread. These are no longer needed, but are preserved for backward compatibility only. */
+
+void tx_thread_fpu_enable(void);
+void tx_thread_fpu_disable(void);
+
+
+/* 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 Cortex-Mx Version 6.2.1 *";
+#else
+#ifdef TX_MISRA_ENABLE
+extern CHAR _tx_version_id[100];
+#else
+extern CHAR _tx_version_id[];
+#endif
+#endif
+
+#endif
diff --git a/ports_arch/ARMv7-M/threadx_modules/inc/txm_module_port.h b/ports_arch/ARMv7-M/threadx_modules/inc/txm_module_port.h
new file mode 100644
index 00000000..bbddb7ab
--- /dev/null
+++ b/ports_arch/ARMv7-M/threadx_modules/inc/txm_module_port.h
@@ -0,0 +1,469 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Module */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* txm_module_port.h Cortex-Mx */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the basic module constants, interface structures, */
+/* and function prototypes. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
+/* 01-31-2022 Scott Larson Modified comments and made */
+/* heap user-configurable, */
+/* resulting in version 6.1.10 */
+/* 07-29-2022 Scott Larson Enabled user-defined and */
+/* default MPU settings, */
+/* resulting in version 6.1.12 */
+/* 10-31-2022 Scott Larson Configure heap size, */
+/* resulting in version 6.2.0 */
+/* 03-08-2023 Scott Larson Set default values for RBAR, */
+/* unify this file for all */
+/* compilers, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+
+#ifndef TXM_MODULE_PORT_H
+#define TXM_MODULE_PORT_H
+
+/* Determine if the optional Modules user define file should be used. */
+
+#ifdef TXM_MODULE_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in txm_module_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "txm_module_user.h"
+#endif
+
+/* It is assumed that the base ThreadX tx_port.h file has been modified to add the
+ following extensions to the ThreadX thread control block (this code should replace
+ the corresponding macro define in tx_port.h):
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_module_instance_ptr; \
+ VOID *tx_thread_module_entry_info_ptr; \
+ ULONG tx_thread_module_current_user_mode; \
+ ULONG tx_thread_module_user_mode; \
+ ULONG tx_thread_module_saved_lr; \
+ VOID *tx_thread_module_kernel_stack_start; \
+ VOID *tx_thread_module_kernel_stack_end; \
+ ULONG tx_thread_module_kernel_stack_size; \
+ VOID *tx_thread_module_stack_ptr; \
+ VOID *tx_thread_module_stack_start; \
+ VOID *tx_thread_module_stack_end; \
+ ULONG tx_thread_module_stack_size; \
+ VOID *tx_thread_module_reserved; \
+ VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_module_instance_ptr; \
+ VOID *tx_thread_module_entry_info_ptr; \
+ ULONG tx_thread_module_current_user_mode; \
+ ULONG tx_thread_module_user_mode; \
+ ULONG tx_thread_module_saved_lr; \
+ VOID *tx_thread_module_kernel_stack_start; \
+ VOID *tx_thread_module_kernel_stack_end; \
+ ULONG tx_thread_module_kernel_stack_size; \
+ VOID *tx_thread_module_stack_ptr; \
+ VOID *tx_thread_module_stack_start; \
+ VOID *tx_thread_module_stack_end; \
+ ULONG tx_thread_module_stack_size; \
+ VOID *tx_thread_module_reserved;
+#endif
+
+The following extensions must also be defined in tx_port.h:
+
+#define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \
+ VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
+
+#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \
+ VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
+
+#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \
+ VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
+
+#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \
+ VOID (*tx_timer_module_expiration_function)(ULONG id);
+*/
+
+/* Users can define the module heap size. */
+#ifndef TXM_MODULE_HEAP_SIZE
+#define TXM_MODULE_HEAP_SIZE 512
+#endif
+
+/* Define the kernel stack size for a module thread. */
+#ifndef TXM_MODULE_KERNEL_STACK_SIZE
+#define TXM_MODULE_KERNEL_STACK_SIZE 768
+#endif
+
+/* For the following 3 access control settings, change TEX and C, B, S (bits 21 through 16 of MPU_RASR)
+ * to reflect your system memory attributes (cache, shareable, memory type). */
+/* Code region access control: privileged read-only, outer & inner write-back, normal memory, shareable. */
+#ifndef TXM_MODULE_MPU_CODE_ACCESS_CONTROL
+#define TXM_MODULE_MPU_CODE_ACCESS_CONTROL 0x06070000
+#endif
+/* Data region access control: execute never, read/write, outer & inner write-back, normal memory, shareable. */
+#ifndef TXM_MODULE_MPU_DATA_ACCESS_CONTROL
+#define TXM_MODULE_MPU_DATA_ACCESS_CONTROL 0x13070000
+#endif
+/* Shared region access control: execute never, read-only, outer & inner write-back, normal memory, shareable. */
+#ifndef TXM_MODULE_MPU_SHARED_ACCESS_CONTROL
+#define TXM_MODULE_MPU_SHARED_ACCESS_CONTROL 0x12070000
+#endif
+
+/* For Cortex-M devices with 16 MPU regions, the last four regions (12-15)
+ are not used by ThreadX. These may be defined by the user.
+ RBAR needs the valid bit and region number set, as MPU alias registers are used. */
+#define TXM_MODULE_MPU_USER_DEFINED_RBAR_12 0x1C
+#define TXM_MODULE_MPU_USER_DEFINED_RASR_12 0
+#define TXM_MODULE_MPU_USER_DEFINED_RBAR_13 0x1D
+#define TXM_MODULE_MPU_USER_DEFINED_RASR_13 0
+#define TXM_MODULE_MPU_USER_DEFINED_RBAR_14 0x1E
+#define TXM_MODULE_MPU_USER_DEFINED_RASR_14 0
+#define TXM_MODULE_MPU_USER_DEFINED_RBAR_15 0x1F
+#define TXM_MODULE_MPU_USER_DEFINED_RASR_15 0
+
+
+/* Users can define these default MPU configuration values.
+
+ If TXM_MODULE_MPU_DEFAULT is *not* defined, the MPU is disabled
+ when a thread that is not owned by a module is running
+ and the defines below are not used.
+
+ If TXM_MODULE_MPU_DEFAULT is defined, the MPU is configured to the
+ below values when a thread that is not owned by a module is running.
+ RBAR needs the valid bit and region number set, as MPU alias registers are used. */
+#define TXM_MODULE_MPU_DEFAULT_RBAR_0 0x10
+#define TXM_MODULE_MPU_DEFAULT_RASR_0 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_1 0x11
+#define TXM_MODULE_MPU_DEFAULT_RASR_1 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_2 0x12
+#define TXM_MODULE_MPU_DEFAULT_RASR_2 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_3 0x13
+#define TXM_MODULE_MPU_DEFAULT_RASR_3 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_4 0x14
+#define TXM_MODULE_MPU_DEFAULT_RASR_4 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_5 0x15
+#define TXM_MODULE_MPU_DEFAULT_RASR_5 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_6 0x16
+#define TXM_MODULE_MPU_DEFAULT_RASR_6 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_7 0x17
+#define TXM_MODULE_MPU_DEFAULT_RASR_7 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_8 0x18
+#define TXM_MODULE_MPU_DEFAULT_RASR_8 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_9 0x19
+#define TXM_MODULE_MPU_DEFAULT_RASR_9 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_10 0x1A
+#define TXM_MODULE_MPU_DEFAULT_RASR_10 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_11 0x1B
+#define TXM_MODULE_MPU_DEFAULT_RASR_11 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_12 0x1C
+#define TXM_MODULE_MPU_DEFAULT_RASR_12 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_13 0x1D
+#define TXM_MODULE_MPU_DEFAULT_RASR_13 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_14 0x1E
+#define TXM_MODULE_MPU_DEFAULT_RASR_14 0
+#define TXM_MODULE_MPU_DEFAULT_RBAR_15 0x1F
+#define TXM_MODULE_MPU_DEFAULT_RASR_15 0
+
+
+/* Define constants specific to the tools the module can be built with for this particular modules port. */
+
+#define TXM_MODULE_IAR_COMPILER 0x00000000
+#define TXM_MODULE_RVDS_COMPILER 0x01000000
+#define TXM_MODULE_GNU_COMPILER 0x02000000
+#define TXM_MODULE_COMPILER_MASK 0xFF000000
+#define TXM_MODULE_OPTIONS_MASK 0x000000FF
+
+
+/* Define the properties for this particular module port. */
+
+#define TXM_MODULE_MEMORY_PROTECTION_ENABLED
+
+#ifdef TXM_MODULE_MEMORY_PROTECTION_ENABLED
+#define TXM_MODULE_REQUIRE_ALLOCATED_OBJECT_MEMORY
+#else
+#define TXM_MODULE_REQUIRE_LOCAL_OBJECT_MEMORY
+#endif
+
+#define TXM_MODULE_USER_MODE 0x00000001
+#define TXM_MODULE_MEMORY_PROTECTION 0x00000002
+#define TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS 0x00000004
+
+
+/* Define the supported options for this module. */
+
+#define TXM_MODULE_MANAGER_SUPPORTED_OPTIONS (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS)
+#define TXM_MODULE_MANAGER_REQUIRED_OPTIONS 0
+
+
+/* Define offset adjustments according to the compiler used to build the module. */
+
+#define TXM_MODULE_IAR_SHELL_ADJUST 24
+#define TXM_MODULE_IAR_START_ADJUST 28
+#define TXM_MODULE_IAR_STOP_ADJUST 32
+#define TXM_MODULE_IAR_CALLBACK_ADJUST 44
+
+#define TXM_MODULE_RVDS_SHELL_ADJUST 0
+#define TXM_MODULE_RVDS_START_ADJUST 0
+#define TXM_MODULE_RVDS_STOP_ADJUST 0
+#define TXM_MODULE_RVDS_CALLBACK_ADJUST 0
+
+#define TXM_MODULE_GNU_SHELL_ADJUST 24
+#define TXM_MODULE_GNU_START_ADJUST 28
+#define TXM_MODULE_GNU_STOP_ADJUST 32
+#define TXM_MODULE_GNU_CALLBACK_ADJUST 44
+
+
+/* Define other module port-specific constants. */
+
+/* Define INLINE_DECLARE to inline for this compiler. */
+#define INLINE_DECLARE inline
+
+#define TXM_MPU_VALID_BIT 0x10
+#define TXM_ENABLE_REGION 0x01
+#define TXM_MODULE_MANAGER_MPU_KERNEL_ENTRY_INDEX 0
+
+/* Shared memory region attributes. */
+#define TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE 1
+#define TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT 0x01000000
+
+/* There are 2 registers to set up each MPU region: MPU_RBAR, MPU_RASR. */
+typedef struct TXM_MODULE_MPU_INFO_STRUCT
+{
+ ULONG txm_module_mpu_region_address;
+ ULONG txm_module_mpu_region_attribute_size;
+} TXM_MODULE_MPU_INFO;
+
+
+#ifdef TXM_MODULE_MANAGER_16_MPU
+
+/* Define the number of MPU entries assigned to the code and data sections.
+ On some Cortex-M7 parts, there are 16 total entries. ThreadX uses one for access
+ to the kernel entry function, thus 15 remain for code and data protection. */
+#define TXM_MODULE_MANAGER_MPU_TOTAL_ENTRIES 16
+#define TXM_MODULE_MANAGER_MPU_CODE_ENTRIES 4
+#define TXM_MODULE_MANAGER_MPU_DATA_ENTRIES 4
+#define TXM_MODULE_MANAGER_MPU_SHARED_ENTRIES 3
+#define TXM_MODULE_MANAGER_MPU_SHARED_INDEX 9
+#define TXM_MODULE_MANAGER_MPU_USER_REGION_INDEX 12
+
+
+/* Define the port-extensions to the module manager instance structure. */
+
+#define TXM_MODULE_MANAGER_PORT_EXTENSION \
+ TXM_MODULE_MPU_INFO txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_TOTAL_ENTRIES]; \
+ ULONG txm_module_instance_shared_memory_count; \
+ ULONG txm_module_instance_shared_memory_address[TXM_MODULE_MANAGER_MPU_SHARED_ENTRIES]; \
+ ULONG txm_module_instance_shared_memory_length[TXM_MODULE_MANAGER_MPU_SHARED_ENTRIES];
+
+#else /* TXM_MODULE_MANAGER_16_MPU is not defined */
+
+/* Define the number of MPU entries assigned to the code and data sections.
+ On Cortex-M3, M4, and some M7 parts, there are 8 total entries. ThreadX uses one for access
+ to the kernel entry function, thus 7 remain for code and data protection. */
+#define TXM_MODULE_MANAGER_MPU_TOTAL_ENTRIES 8
+#define TXM_MODULE_MANAGER_CODE_MPU_ENTRIES 4
+#define TXM_MODULE_MANAGER_DATA_MPU_ENTRIES 3
+#define TXM_MODULE_MANAGER_SHARED_MPU_REGION 4
+
+/* Define the port-extensions to the module manager instance structure. */
+
+#define TXM_MODULE_MANAGER_PORT_EXTENSION \
+ TXM_MODULE_MPU_INFO txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_TOTAL_ENTRIES]; \
+ ULONG txm_module_instance_shared_memory_address; \
+ ULONG txm_module_instance_shared_memory_length;
+
+#endif /* TXM_MODULE_MANAGER_16_MPU */
+
+
+/* Define the memory fault information structure that is populated when a memory fault occurs. */
+typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT
+{
+ TX_THREAD *txm_module_manager_memory_fault_info_thread_ptr;
+ VOID *txm_module_manager_memory_fault_info_code_location;
+ ULONG txm_module_manager_memory_fault_info_shcsr;
+ ULONG txm_module_manager_memory_fault_info_cfsr;
+ ULONG txm_module_manager_memory_fault_info_mmfar;
+ ULONG txm_module_manager_memory_fault_info_bfar;
+ ULONG txm_module_manager_memory_fault_info_control;
+ ULONG txm_module_manager_memory_fault_info_sp;
+ ULONG txm_module_manager_memory_fault_info_r0;
+ ULONG txm_module_manager_memory_fault_info_r1;
+ ULONG txm_module_manager_memory_fault_info_r2;
+ ULONG txm_module_manager_memory_fault_info_r3;
+ ULONG txm_module_manager_memory_fault_info_r4;
+ ULONG txm_module_manager_memory_fault_info_r5;
+ ULONG txm_module_manager_memory_fault_info_r6;
+ ULONG txm_module_manager_memory_fault_info_r7;
+ ULONG txm_module_manager_memory_fault_info_r8;
+ ULONG txm_module_manager_memory_fault_info_r9;
+ ULONG txm_module_manager_memory_fault_info_r10;
+ ULONG txm_module_manager_memory_fault_info_r11;
+ ULONG txm_module_manager_memory_fault_info_r12;
+ ULONG txm_module_manager_memory_fault_info_lr;
+ ULONG txm_module_manager_memory_fault_info_xpsr;
+} TXM_MODULE_MANAGER_MEMORY_FAULT_INFO;
+
+
+#define TXM_MODULE_MANAGER_FAULT_INFO \
+ TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info;
+
+/* Define the macro to check the code alignment. */
+
+#define TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) \
+ { \
+ ULONG temp; \
+ temp = (ULONG) module_location; \
+ temp = temp & (code_alignment - 1); \
+ if (temp) \
+ { \
+ _tx_mutex_put(&_txm_module_manager_mutex); \
+ return(TXM_MODULE_ALIGNMENT_ERROR); \
+ } \
+ }
+
+
+/* Define the macro to adjust the alignment and size for code/data areas. */
+
+#define TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size, code_alignment, data_size, data_alignment) _txm_module_manager_alignment_adjust(module_preamble, &code_size, &code_alignment, &data_size, &data_alignment);
+
+
+/* Define the macro to adjust the symbols in the module preamble. */
+
+#define TXM_MODULE_MANAGER_CALCULATE_ADJUSTMENTS(properties, shell_function_adjust, start_function_adjust, stop_function_adjust, callback_function_adjust) \
+ if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_IAR_COMPILER) \
+ { \
+ shell_function_adjust = TXM_MODULE_IAR_SHELL_ADJUST; \
+ start_function_adjust = TXM_MODULE_IAR_START_ADJUST; \
+ stop_function_adjust = TXM_MODULE_IAR_STOP_ADJUST; \
+ callback_function_adjust = TXM_MODULE_IAR_CALLBACK_ADJUST; \
+ } \
+ else if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_RVDS_COMPILER) \
+ { \
+ shell_function_adjust = TXM_MODULE_RVDS_SHELL_ADJUST; \
+ start_function_adjust = TXM_MODULE_RVDS_START_ADJUST; \
+ stop_function_adjust = TXM_MODULE_RVDS_STOP_ADJUST; \
+ callback_function_adjust = TXM_MODULE_RVDS_CALLBACK_ADJUST; \
+ } \
+ else \
+ { \
+ shell_function_adjust = TXM_MODULE_GNU_SHELL_ADJUST; \
+ start_function_adjust = TXM_MODULE_GNU_START_ADJUST; \
+ stop_function_adjust = TXM_MODULE_GNU_STOP_ADJUST; \
+ callback_function_adjust = TXM_MODULE_GNU_CALLBACK_ADJUST; \
+ }
+
+
+/* Define the macro to populate the thread control block with module port-specific information.
+ Check if the module is in user mode and set up txm_module_thread_entry_info_kernel_call_dispatcher accordingly.
+*/
+
+#define TXM_MODULE_MANAGER_THREAD_SETUP(thread_ptr, module_instance) \
+ thread_ptr -> tx_thread_module_current_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE; \
+ thread_ptr -> tx_thread_module_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE; \
+ if (thread_ptr -> tx_thread_module_user_mode) \
+ { \
+ thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_user_mode_entry; \
+ } \
+ else \
+ { \
+ thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_kernel_dispatch; \
+ }
+
+
+/* Define the macro to populate the module control block with module port-specific information.
+ If memory protection is enabled, set up the MPU registers.
+*/
+#define TXM_MODULE_MANAGER_MODULE_SETUP(module_instance) \
+ if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) \
+ { \
+ if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) \
+ { \
+ _txm_module_manager_mm_register_setup(module_instance); \
+ } \
+ } \
+ else \
+ { \
+ /* Do nothing. */ \
+ }
+
+/* Define the macro to perform port-specific functions when unloading the module. */
+/* Nothing needs to be done for this port. */
+#define TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance)
+
+
+/* Define the macros to perform port-specific checks when passing pointers to the kernel. */
+
+/* Define macro to make sure object is inside the module's data. */
+#ifdef TXM_MODULE_MANAGER_16_MPU
+#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \
+ _txm_module_manager_inside_data_check(module_instance, obj_ptr, obj_size)
+#else
+#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \
+ /* Check for overflow. */ \
+ (((obj_ptr) < ((obj_ptr) + (obj_size))) && \
+ /* Check if it's inside module data. */ \
+ ((((obj_ptr) >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) && \
+ (((obj_ptr) + (obj_size)) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_data_end + 1))) || \
+ /* Check if it's inside shared memory. */ \
+ (((obj_ptr) >= (ALIGN_TYPE) module_instance -> txm_module_instance_shared_memory_address) && \
+ (((obj_ptr) + (obj_size)) <= (ALIGN_TYPE) (module_instance -> txm_module_instance_shared_memory_address + module_instance -> txm_module_instance_shared_memory_length)))))
+#endif
+
+/* Define some internal prototypes to this module port. */
+
+#ifndef TX_SOURCE_CODE
+#define txm_module_manager_memory_fault_notify _txm_module_manager_memory_fault_notify
+#endif
+
+
+#define TXM_MODULE_MANAGER_ADDITIONAL_PROTOTYPES \
+VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment); \
+VOID _txm_module_manager_memory_fault_handler(VOID); \
+UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)); \
+VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \
+ULONG _txm_power_of_two_block_size(ULONG size); \
+ULONG _txm_module_manager_calculate_srd_bits(ULONG block_size, ULONG length); \
+ULONG _txm_module_manager_region_size_get(ULONG block_size); \
+UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size);
+
+#define TXM_MODULE_MANAGER_VERSION_ID \
+CHAR _txm_module_manager_version_id[] = \
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Module Cortex-Mx Version 6.2.1 *";
+
+#endif
diff --git a/ports_arch/ARMv8-M/README.md b/ports_arch/ARMv8-M/README.md
new file mode 100644
index 00000000..327f925c
--- /dev/null
+++ b/ports_arch/ARMv8-M/README.md
@@ -0,0 +1,5 @@
+# ARMv8-M architecture ports
+
+The ThreadX, ThreadX SMP, ThreadX Modules and ThreadX SMP Modules ports for ARMv8 share many files in common.
+To make work more efficient these files are internally tracked only once and copied over to specific ports for users.
+
diff --git a/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt b/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt
new file mode 100644
index 00000000..5ad3b8e7
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt
@@ -0,0 +1,21 @@
+target_sources(${PROJECT_NAME} PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_allocate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_free.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S
+ ${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.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_allocate.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_free.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
+)
+
+target_include_directories(${PROJECT_NAME} PUBLIC
+ inc
+)
diff --git a/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt b/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt
new file mode 100644
index 00000000..5821892f
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt
@@ -0,0 +1,228 @@
+ Microsoft's Azure RTOS ThreadX for Cortex-Mxx
+
+ Using the AC6 Tools in Keil uVision
+
+1. Import the ThreadX Projects
+
+In order to build the ThreadX library and the ThreadX demonstration, first open
+the AzureRTOS.uvmpw workspace (located in the "example_build" directory)
+into Keil.
+
+
+2. Building the ThreadX run-time Library
+
+Building the ThreadX library is easy; simply set the ThreadX_Library project
+as active, then then build the library. You should now observe the compilation
+and assembly of the ThreadX library. This project build produces the ThreadX
+library file ThreadX_Library.lib.
+Files tx_thread_stack_error_handler.c and tx_thread_stack_error_notify.c
+replace the common files of the same name.
+
+3. Demonstration System
+
+The ThreadX demonstration is designed to execute under the Keil debugger on the
+FVP_MPS2_Cortex-Mxx_MDK simulator.
+
+Building the demonstration is easy; simply select the "Batch Build" button.
+You should now observe the compilation and assembly of the ThreadX demonstration of
+both the demo_secure_zone and demo_threadx_non-secure_zone projects.
+Then click the Start/Stop Debug Session button to start the simulator and begin debugging.
+You are now ready to execute the ThreadX demonstration.
+
+
+4. System Initialization
+
+The entry point in ThreadX for the Cortex-Mxx using AC6 tools uses the standard AC6
+Cortex-Mxx reset sequence. From the reset vector the C runtime will be initialized.
+
+The ThreadX tx_initialize_low_level.s file is responsible for setting up
+various system data structures, the vector area, and a periodic timer interrupt
+source.
+
+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.
+
+
+5. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-Mxx version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 LR Interrupted LR (LR at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 LR Interrupted LR (LR at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+6. Improving Performance
+
+To make ThreadX and the application(s) run faster, you can enable
+all compiler 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.
+
+
+7. Interrupt Handling
+
+ThreadX provides complete and high-performance interrupt handling for Cortex-Mxx
+targets. There are a certain set of requirements that are defined in the
+following sub-sections:
+
+
+7.1 Vector Area
+
+The Cortex-Mxx vectors start at the label __Vectors or similar. The application may modify
+the vector area according to its needs. There is code in tx_initialize_low_level() that will
+configure the vector base register.
+
+
+7.2 Managed Interrupts
+
+ISRs can be written completely in C (or assembly language) without any calls to
+_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the
+ThreadX API that is available to ISRs.
+
+ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
+
+void your_C_isr(void)
+{
+
+ /* ISR processing goes here, including any needed function calls. */
+}
+
+ISRs written in assembly language will take the form:
+
+
+ .global your_assembly_isr
+ .thumb_func
+your_assembly_isr:
+; VOID your_assembly_isr(VOID)
+; {
+ PUSH {r0, lr}
+;
+; /* Do interrupt handler work here */
+; /* BL <your interrupt routine in C> */
+
+ POP {r0, lr}
+ BX lr
+; }
+
+Note: the Cortex-Mxx requires exception handlers to be thumb labels, this implies bit 0 set.
+To accomplish this, the declaration of the label has to be preceded by the assembler directive
+.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
+be inserted in the correct location in the interrupt vector table. This table is typically
+located in either your runtime startup file or in the tx_initialize_low_level.s file.
+
+
+8. FPU Support
+
+ThreadX for Cortex-Mxx supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context.
+
+
+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:
+
+06-02-2021 Release 6.1.7 changes:
+ tx_port.h Remove unneeded include file
+ tx_thread_secure_stack_initialize.S New file
+ tx_thread_schedule.S Added secure stack initialize to SVC hander
+ tx_thread_secure_stack.c Fixed stack pointer save, initialize in handler mode
+
+04-02-2021 Release 6.1.6 changes:
+ tx_port.h Updated macro definition
+ tx_thread_schedule.s Added low power support
+
+03-02-2021 The following files were changed/added for version 6.1.5:
+ tx_port.h Added ULONG64_DEFINED
+
+09-30-2020 Initial ThreadX 6.1 version for Cortex-Mxx using AC6 tools.
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S
new file mode 100644
index 00000000..cf146cc2
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S
@@ -0,0 +1,283 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+/* Setup the stack and heap areas. */
+
+STACK_SIZE = 0x00000400
+HEAP_SIZE = 0x00000000
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_initialize_low_level
+ .thumb_func
+.type _tx_initialize_low_level, function
+_tx_initialize_low_level:
+
+ /* Disable interrupts during ThreadX initialization. */
+ CPSID i
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ LDR r1, =Image$$ARM_LIB_STACK$$ZI$$Limit // Build first free address
+ ADD r1, r1, #4 //
+ STR r1, [r0] // Setup first unused memory pointer
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =__Vectors // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Enable the cycle count register. */
+ LDR r0, =0xE0001000 // Build address of DWT register
+ LDR r1, [r0] // Pickup the current value
+ ORR r1, r1, #1 // Set the CYCCNTENA bit
+ STR r1, [r0] // Enable the cycle count register
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =__Vectors // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+
+/* Define shells for each of the unused vectors. */
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_BadHandler
+ .thumb_func
+.type __tx_BadHandler, function
+__tx_BadHandler:
+ B __tx_BadHandler
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_IntHandler
+ .thumb_func
+.type __tx_IntHandler, function
+__tx_IntHandler:
+// VOID InterruptHandler (VOID)
+// {
+ PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment)
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ /* Do interrupt handler work here */
+ /* .... */
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0,lr}
+ BX LR
+// }
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global SysTick_Handler
+ .thumb_func
+.type SysTick_Handler, function
+SysTick_Handler:
+// VOID TimerInterruptHandler (VOID)
+// {
+ PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment)
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0,lr}
+ BX LR
+// }
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global HardFault_Handler
+ .thumb_func
+.type HardFault_Handler, function
+HardFault_Handler:
+ B HardFault_Handler
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global UsageFault_Handler
+ .thumb_func
+.type UsageFault_Handler, function
+UsageFault_Handler:
+ CPSID i // Disable interrupts
+ // Check for stack limit fault
+ LDR r0, =0xE000ED28 // CFSR address
+ LDR r1,[r0] // Pick up CFSR
+ TST r1, #0x00100000 // Check for Stack Overflow
+_unhandled_usage_loop:
+ BEQ _unhandled_usage_loop // If not stack overflow then loop
+
+ // Handle stack overflow
+ STR r1, [r0] // Clear CFSR flag(s)
+
+#ifdef __ARM_PCS_VFP
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Store the value
+#endif
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r0,[r0] // Pick up current thread pointer
+ PUSH {r0,lr} // Save LR (and r0 to maintain stack alignment)
+ BL _tx_thread_stack_error_handler // Call ThreadX/user handler
+ POP {r0,lr} // Restore LR and dummy reg
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ // Call the thread exit function to indicate the thread is no longer executing.
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from UsageFault_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+ CPSIE i // Enable interrupts
+ BX lr // Return from exception
+
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_NMIHandler
+ .thumb_func
+.type __tx_NMIHandler, function
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_DBGHandler
+ .thumb_func
+.type __tx_DBGHandler, function
+__tx_DBGHandler:
+ B __tx_DBGHandler
+
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_misra.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_misra.S
new file mode 100644
index 00000000..c84d8576
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_misra.S
@@ -0,0 +1,723 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ #define SHT_PROGBITS 0x1
+
+ .global __aeabi_memset
+ .global _tx_thread_current_ptr
+ .global _tx_thread_interrupt_disable
+ .global _tx_thread_interrupt_restore
+ .global _tx_thread_stack_analyze
+ .global _tx_thread_stack_error_handler
+ .global _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_trace_buffer_current_ptr
+ .global _tx_trace_buffer_end_ptr
+ .global _tx_trace_buffer_start_ptr
+ .global _tx_trace_event_enable_bits
+ .global _tx_trace_full_notify_function
+ .global _tx_trace_header_ptr
+#endif
+
+ .global _tx_misra_always_true
+ .global _tx_misra_block_pool_to_uchar_pointer_convert
+ .global _tx_misra_byte_pool_to_uchar_pointer_convert
+ .global _tx_misra_char_to_uchar_pointer_convert
+ .global _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_indirect_void_to_uchar_pointer_convert
+ .global _tx_misra_memset
+ .global _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_object_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_pointer_to_ulong_convert
+ .global _tx_misra_status_get
+ .global _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_time_stamp_get
+#endif
+ .global _tx_misra_timer_indirect_to_void_pointer_convert
+ .global _tx_misra_timer_pointer_add
+ .global _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_trace_event_insert
+#endif
+ .global _tx_misra_uchar_pointer_add
+ .global _tx_misra_uchar_pointer_dif
+ .global _tx_misra_uchar_pointer_sub
+ .global _tx_misra_uchar_to_align_type_pointer_convert
+ .global _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_entry_pointer_convert
+ .global _tx_misra_uchar_to_header_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ .global _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_object_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_void_pointer_convert
+ .global _tx_misra_ulong_pointer_add
+ .global _tx_misra_ulong_pointer_dif
+ .global _tx_misra_ulong_pointer_sub
+ .global _tx_misra_ulong_to_pointer_convert
+ .global _tx_misra_ulong_to_thread_pointer_convert
+ .global _tx_misra_user_timer_pointer_get
+ .global _tx_misra_void_to_block_pool_pointer_convert
+ .global _tx_misra_void_to_byte_pool_pointer_convert
+ .global _tx_misra_void_to_event_flags_pointer_convert
+ .global _tx_misra_void_to_indirect_uchar_pointer_convert
+ .global _tx_misra_void_to_mutex_pointer_convert
+ .global _tx_misra_void_to_queue_pointer_convert
+ .global _tx_misra_void_to_semaphore_pointer_convert
+ .global _tx_misra_void_to_thread_pointer_convert
+ .global _tx_misra_void_to_uchar_pointer_convert
+ .global _tx_misra_void_to_ulong_pointer_convert
+ .global _tx_misra_ipsr_get
+ .global _tx_misra_control_get
+ .global _tx_misra_control_set
+#ifdef __ARM_FP
+ .global _tx_misra_fpccr_get
+ .global _tx_misra_vfp_touch
+#endif
+
+ .global _tx_misra_event_flags_group_not_used
+ .global _tx_misra_event_flags_set_notify_not_used
+ .global _tx_misra_queue_not_used
+ .global _tx_misra_queue_send_notify_not_used
+ .global _tx_misra_semaphore_not_used
+ .global _tx_misra_semaphore_put_notify_not_used
+ .global _tx_misra_thread_entry_exit_notify_not_used
+ .global _tx_misra_thread_not_used
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+ .syntax unified
+ .thumb_func
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ .text
+ .thumb_func
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N _tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N _tx_misra_message_copy_1
+_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N _tx_misra_message_copy_2
+_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR R2,=0x54485244
+ CMP R1,R2
+ BNE.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_3
+_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N _tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N _tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N _tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N _tx_misra_trace_event_insert_4
+ LDR.N R0,DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N _tx_misra_trace_event_insert_0
+_tx_misra_trace_event_insert_4:
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ .data
+DataTable2_1:
+ .word _tx_trace_buffer_current_ptr
+
+ .data
+DataTable2_2:
+ .word _tx_trace_event_enable_bits
+
+ .data
+DataTable2_5:
+ .word _tx_trace_buffer_end_ptr
+
+ .data
+DataTable2_6:
+ .word _tx_trace_buffer_start_ptr
+
+ .data
+DataTable2_7:
+ .word _tx_trace_header_ptr
+
+ .data
+DataTable2_8:
+ .word _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ .data
+DataTable2_3:
+ .word _tx_thread_system_state
+
+ .data
+DataTable2_4:
+ .word _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARM_FP
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ .data
+ .word 0
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_restore.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..af6570cc
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_restore.S
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_exit
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is not needed for Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_context_restore
+ .thumb_func
+.type _tx_thread_context_restore, function
+_tx_thread_context_restore:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_save.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_save.S
new file mode 100644
index 00000000..a95c14f7
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_context_save.S
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_enter
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is not needed for Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_context_save
+ .thumb_func
+.type _tx_thread_context_save, function
+_tx_thread_context_save:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_control.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..dbb9d24b
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_control.S
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ .section .text
+ .balign 4
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_interrupt_control
+ .thumb_func
+.type _tx_thread_interrupt_control, function
+_tx_thread_interrupt_control:
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_disable.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_disable.S
new file mode 100644
index 00000000..a61ec0c6
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_disable.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_interrupt_disable
+ .thumb_func
+.type _tx_thread_interrupt_disable, function
+_tx_thread_interrupt_disable:
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_restore.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_restore.S
new file mode 100644
index 00000000..bec99cf5
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_interrupt_restore.S
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_interrupt_restore
+ .thumb_func
+.type _tx_thread_interrupt_restore, function
+_tx_thread_interrupt_restore:
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S
new file mode 100644
index 00000000..aae38194
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S
@@ -0,0 +1,399 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_thread_enter
+ .global _tx_execution_thread_exit
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 04-02-2021 Scott Larson Modified comment(s), added */
+/* low power code, */
+/* resulting in version 6.1.6 */
+/* 06-02-2021 Scott Larson Added secure stack initialize */
+/* in SVC handler, */
+/* resulting in version 6.1.7 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 03-08-2023 Scott Larson Added preproc FPU option, */
+/* included tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_schedule
+ .thumb_func
+.type _tx_thread_schedule, function
+_tx_thread_schedule:
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __ARM_PCS_VFP
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global PendSV_Handler
+ .thumb_func
+.type PendSV_Handler, function
+ /* Get current thread value and new thread pointer. */
+PendSV_Handler:
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARM_PCS_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+ STR r12, [r1, #8] // Save the thread stack pointer
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // Save secure context
+ LDR r5, [r1,#0x90] // Load secure stack index
+ CBZ r5, _skip_secure_save // Skip save if there is no secure context
+ PUSH {r0,r1,r2,r3} // Save scratch registers
+ MOV r0, r1 // Move thread ptr to r0
+ BL _tx_thread_secure_stack_context_save // Save secure stack
+ POP {r0,r1,r2,r3} // Restore secure registers
+_skip_secure_save:
+#endif
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // Restore secure context
+ LDR r0, [r1,#0x90] // Load secure stack index
+ CBZ r0, _skip_secure_restore // Skip restore if there is no secure context
+ PUSH {r0,r1} // Save r1 (and dummy r0)
+ MOV r0, r1 // Move thread ptr to r0
+ BL _tx_thread_secure_stack_context_restore // Restore secure stack
+ POP {r0,r1} // Restore r1 (and dummy r0)
+_skip_secure_restore:
+#endif
+
+ /* Restore the thread context and PSP. */
+ LDR r12, [r1, #12] // Get stack start
+ MSR PSPLIM, r12 // Set stack limit
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARM_PCS_VFP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // SVC_Handler is not needed when ThreadX is running in single mode.
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global SVC_Handler
+ .thumb_func
+.type SVC_Handler, function
+SVC_Handler:
+ TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2
+ ITE EQ
+ MRSEQ r0, MSP // Get MSP if return stack is MSP
+ MRSNE r0, PSP // Get PSP if return stack is PSP
+
+ LDR r1, [r0,#24] // Load saved PC from stack
+ LDRB r1, [r1,#-2] // Load SVC number
+
+ CMP r1, #1 // Is it a secure stack allocate request?
+ BEQ _tx_svc_secure_alloc // Yes, go there
+
+ CMP r1, #2 // Is it a secure stack free request?
+ BEQ _tx_svc_secure_free // Yes, go there
+
+ CMP r1, #3 // Is it a secure stack init request?
+ BEQ _tx_svc_secure_init // Yes, go there
+
+ // Unknown SVC argument - just return
+ BX lr
+
+_tx_svc_secure_alloc:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ LDM r0, {r0-r3} // Load function parameters from stack
+ BL _tx_thread_secure_mode_stack_allocate
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ STR r0,[r12] // Store function return value
+ BX lr
+_tx_svc_secure_free:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ LDM r0, {r0-r3} // Load function parameters from stack
+ BL _tx_thread_secure_mode_stack_free
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ STR r0,[r12] // Store function return value
+ BX lr
+_tx_svc_secure_init:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ BL _tx_thread_secure_mode_stack_initialize
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ BX lr
+#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_vfp_access
+ .thumb_func
+.type _tx_vfp_access, function
+_tx_vfp_access:
+#ifdef __ARM_PCS_VFP
+ VMOV.F32 s0, s0 // Simply access the VFP
+#endif
+ BX lr // Return to caller
+.end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack.c b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack.c
new file mode 100644
index 00000000..feb87e77
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack.c
@@ -0,0 +1,592 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "tx_api.h"
+
+/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined,
+ no secure stack functionality is needed. */
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+
+#define TX_SOURCE_CODE
+
+#include "cmsis_compiler.h" /* For intrinsic functions. */
+#include "tx_secure_interface.h" /* Interface for NS code. */
+
+/* Minimum size of secure stack. */
+#ifndef TX_THREAD_SECURE_STACK_MINIMUM
+#define TX_THREAD_SECURE_STACK_MINIMUM 256
+#endif
+/* Maximum size of secure stack. */
+#ifndef TX_THREAD_SECURE_STACK_MAXIMUM
+#define TX_THREAD_SECURE_STACK_MAXIMUM 1024
+#endif
+
+/* 8 bytes added to stack size to "seal" stack. */
+#define TX_THREAD_STACK_SEAL_SIZE 8
+#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5
+
+/* max number of Secure context */
+#ifndef TX_MAX_SECURE_CONTEXTS
+#define TX_MAX_SECURE_CONTEXTS 32
+#endif
+#define TX_INVALID_SECURE_CONTEXT_IDX (-1)
+
+/* Secure stack info struct to hold stack start, stack limit,
+ current stack pointer, and pointer to owning thread.
+ This will be allocated for each thread with a secure stack. */
+typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
+{
+ VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */
+ VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */
+ VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */
+ TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */
+ INT tx_next_free_index; /* Next free index of free secure context */
+} TX_THREAD_SECURE_STACK_INFO;
+
+/* Static secure contexts */
+static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS];
+/* Head of free secure context */
+static INT tx_head_free_index = 0U;
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_initialize Cortex-Mxx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes secure mode to use PSP stack. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* status */
+/* */
+/* 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 */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 06-02-2021 Scott Larson Modified comment(s), and */
+/* changed name, execute in */
+/* handler mode, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_initialize(void)
+{
+UINT status;
+INT index;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ if (__get_IPSR() == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+ /* Set secure mode to use PSP. */
+ __set_CONTROL(__get_CONTROL() | 2);
+
+ /* 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);
+
+ for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++)
+ {
+
+ /* Check last index and mark next free to invalid index */
+ if(index == (TX_MAX_SECURE_CONTEXTS - 1))
+ {
+ tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+ else
+ {
+ tx_thread_secure_context[index].tx_next_free_index = index + 1;
+ }
+ }
+
+ status = TX_SUCCESS;
+ }
+ return status;
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_allocate Cortex-Mxx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allocates a thread's secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of stack to allocates */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_SIZE_ERROR Invalid stack size */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* __get_IPSR Intrinsic to get IPSR */
+/* malloc Compiler's malloc 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 */
+/* */
+/* SVC Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* added stack sealing, */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+UCHAR *stack_mem;
+INT secure_context_index;
+
+ status = TX_SUCCESS;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ if (__get_IPSR() == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+ else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM)
+ {
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Check if thread already has secure stack allocated. */
+ else if (thread_ptr -> tx_thread_secure_stack_context != 0)
+ {
+ status = TX_THREAD_ERROR;
+ }
+
+ else
+ {
+ TX_DISABLE
+
+ /* Allocate free index for secure stack info. */
+ if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX)
+ {
+ secure_context_index = tx_head_free_index;
+ tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index;
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+ else
+ {
+ secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+
+ TX_RESTORE
+
+ if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX)
+ {
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* If stack info allocated, allocate a stack & seal. */
+ stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE);
+
+ if(stack_mem != TX_NULL)
+ {
+ /* Secure stack has been allocated, save in the stack info struct. */
+ info_ptr -> tx_thread_secure_stack_limit = stack_mem;
+ info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size;
+ info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start;
+ info_ptr -> tx_thread_ptr = thread_ptr;
+
+ /* Seal bottom of stack. */
+ *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE;
+
+ /* Save secure context id (i.e non-zero base index) in thread. */
+ thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1);
+
+ /* Check if this thread is running by looking at its stack start and PSPLIM_NS */
+ if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == __TZ_get_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));
+ }
+ }
+
+ else
+ {
+ TX_DISABLE
+
+ /* Stack not allocated, free the info struct. */
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
+ tx_head_free_index = secure_context_index;
+ TX_RESTORE
+
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ else
+ {
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ return(status);
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_free Cortex-Mxx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function frees a thread's secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* __get_IPSR Intrinsic to get IPSR */
+/* free Compiler's free() function */
+/* */
+/* CALLED BY */
+/* */
+/* SVC Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+INT secure_context_index;
+
+ status = TX_SUCCESS;
+
+ /* Pickup stack info id from thread. */
+ secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ if (__get_IPSR() == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Pickup stack info from static array of secure contexts. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ status = TX_THREAD_ERROR;
+ }
+
+ else
+ {
+
+ /* Free secure stack. */
+ free(info_ptr -> tx_thread_secure_stack_limit);
+
+ TX_DISABLE
+
+ /* Free info struct. */
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
+ tx_head_free_index = secure_context_index;
+ TX_RESTORE
+
+ /* Clear secure context from thread. */
+ thread_ptr -> tx_thread_secure_stack_context = 0;
+ }
+ }
+
+ return(status);
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_context_save Cortex-Mxx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves context of the secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* 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 */
+/* */
+/* CALLED BY */
+/* */
+/* PendSV Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 06-02-2021 Scott Larson Fix stack pointer save, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr)
+{
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+ULONG sp;
+INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* This function should be called from scheduler only. */
+ if (__get_IPSR() == 0)
+ {
+ return;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ return;
+ }
+
+ /* Pickup the secure context pointer. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ return;
+ }
+
+ /* Check that stack pointer is in range */
+ sp = __get_PSP();
+ if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) ||
+ (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start))
+ {
+ return;
+ }
+
+ /* Save stack pointer. */
+ info_ptr -> tx_thread_secure_stack_ptr = (VOID *) 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);
+
+ return;
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_context_restore Cortex-Mxx/AC6 */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function restores context of the secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* __get_IPSR Intrinsic to get IPSR */
+/* __set_PSPLIM Intrinsic to set PSP limit */
+/* __set_PSP Intrinsic to set PSP */
+/* */
+/* CALLED BY */
+/* */
+/* PendSV Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr)
+{
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* This function should be called from scheduler only. */
+ if (__get_IPSR() == 0)
+ {
+ return;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ return;
+ }
+
+ /* Pickup the secure context pointer. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ return;
+ }
+
+ /* 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);
+
+ return;
+}
+
+#endif
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_allocate.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_allocate.S
new file mode 100644
index 00000000..5c4897aa
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_allocate.S
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_allocate Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to allocate a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of secure stack to */
+/* allocate */
+/* */
+/* OUTPUT */
+/* */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* SVC 1 */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_secure_stack_allocate
+ .thumb_func
+.type _tx_thread_secure_stack_allocate, function
+_tx_thread_secure_stack_allocate:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ MRS r3, PRIMASK // Save interrupt mask
+ CPSIE i // Enable interrupts for SVC call
+ SVC 1
+ CMP r3, #0 // If interrupts enabled, just return
+ BEQ _alloc_return_interrupt_enabled
+ CPSID i // Otherwise, disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+_alloc_return_interrupt_enabled:
+ BX lr
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_free.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_free.S
new file mode 100644
index 00000000..87703b70
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_free.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_free Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to free a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* SVC 2 */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_secure_stack_free
+ .thumb_func
+.type _tx_thread_secure_stack_free, function
+_tx_thread_secure_stack_free:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ MRS r3, PRIMASK // Save interrupt mask
+ CPSIE i // Enable interrupts for SVC call
+ SVC 2
+ CMP r3, #0 // If interrupts enabled, just return
+ BEQ _free_return_interrupt_enabled
+ CPSID i // Otherwise, disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+_free_return_interrupt_enabled:
+ BX lr
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_initialize.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_initialize.S
new file mode 100644
index 00000000..b44f5b9a
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_secure_stack_initialize.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_initialize Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to initialize a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* none */
+/* */
+/* OUTPUT */
+/* */
+/* none */
+/* */
+/* CALLS */
+/* */
+/* SVC 3 */
+/* */
+/* CALLED BY */
+/* */
+/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 07-29-2022 Scott Larson Modified comments and changed */
+/* secure stack initialization */
+/* macro to port-specific, */
+/* resulting in version 6.1.12 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_secure_stack_initialize(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_secure_stack_initialize
+ .thumb_func
+.type _tx_thread_secure_stack_initialize, function
+_tx_thread_secure_stack_initialize:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ CPSIE i // Enable interrupts for SVC call
+ SVC 3
+ CPSID i // Disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+ BX lr
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_stack_build.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..5b94225f
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_stack_build.S
@@ -0,0 +1,145 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_stack_build
+ .thumb_func
+.type _tx_thread_stack_build, function
+_tx_thread_stack_build:
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+#ifdef TX_SINGLE_MODE_SECURE
+ LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode
+#else
+ LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP
+#endif
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S
new file mode 100644
index 00000000..0f54bd00
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S
@@ -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 */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_system_return
+ .thumb_func
+.type _tx_thread_system_return, function
+_tx_thread_system_return:
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context:
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_timer_interrupt.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..8081f7a7
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_timer_interrupt.S
@@ -0,0 +1,248 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mxx/AC6 */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_timer_interrupt
+ .thumb_func
+.type _tx_timer_interrupt, function
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ PUSH {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ POP {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_allocate.c b/ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_allocate.c
new file mode 100644
index 00000000..caa47139
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_allocate.c
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_allocate Cortex-Mxx */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the secure stack allocate */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of secure stack to */
+/* allocate */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_secure_stack_allocate Actual stack alloc function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+{
+#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE)
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+UINT status;
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+ /* Is call from an interrupt and not initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+ /* Call actual secure stack allocate function. */
+ status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size);
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_free.c b/ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_free.c
new file mode 100644
index 00000000..0e1efcf4
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/ac6/src/txe_thread_secure_stack_free.c
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_thread_secure_stack_free Cortex-Mxx */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the secure stack free */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_secure_stack_free Actual stack free function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr)
+{
+#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE)
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+UINT status;
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+ /* Is call from an interrupt and not initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual secure stack allocate function. */
+ status = _tx_thread_secure_stack_free(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
diff --git a/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt b/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt
new file mode 100644
index 00000000..5ad3b8e7
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt
@@ -0,0 +1,21 @@
+target_sources(${PROJECT_NAME} PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_allocate.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_free.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S
+ ${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.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_allocate.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_free.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
+)
+
+target_include_directories(${PROJECT_NAME} PUBLIC
+ inc
+)
diff --git a/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt b/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt
new file mode 100644
index 00000000..4a6f5660
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt
@@ -0,0 +1,210 @@
+ Microsoft's Azure RTOS ThreadX for Cortex-Mxx
+
+ Using the GNU Tools
+
+1. Building the ThreadX run-time Library
+
+Import all ThreadX common and port-specific source files into a GNU project.
+Configure the project to build a library rather than an executable. This
+results in the ThreadX run-time library file tx.a, which is needed by
+the application.
+Files tx_thread_stack_error_handler.c and tx_thread_stack_error_notify.c
+replace the common files of the same name.
+
+2. Demonstration System
+
+No demonstration project is provided.
+
+
+3. System Initialization
+
+The entry point in ThreadX for the Cortex-Mxx using gnu tools uses the standard GNU
+Cortex-Mxx reset sequence. From the reset vector the C runtime will be initialized.
+
+The ThreadX tx_initialize_low_level.S file is responsible for setting up
+various system data structures, the vector area, and a periodic timer interrupt
+source.
+
+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.
+
+
+4. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-Mxx version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 LR Interrupted LR (LR at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 LR Interrupted LR (LR at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+5. Improving Performance
+
+To make ThreadX and the application(s) run faster, you can enable
+all compiler 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.
+
+
+6. Interrupt Handling
+
+ThreadX provides complete and high-performance interrupt handling for Cortex-Mxx
+targets. There are a certain set of requirements that are defined in the
+following sub-sections:
+
+
+6.1 Vector Area
+
+The Cortex-Mxx vectors start at the label __tx_vectors or similar. The application may modify
+the vector area according to its needs. There is code in tx_initialize_low_level() that will
+configure the vector base register.
+
+
+6.2 Managed Interrupts
+
+ISRs can be written completely in C (or assembly language) without any calls to
+_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the
+ThreadX API that is available to ISRs.
+
+ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
+
+void your_C_isr(void)
+{
+
+ /* ISR processing goes here, including any needed function calls. */
+}
+
+ISRs written in assembly language will take the form:
+
+
+ .global your_assembly_isr
+ .thumb_func
+your_assembly_isr:
+ PUSH {r0, lr}
+;
+; /* Do interrupt handler work here */
+; /* BL <your interrupt routine in C> */
+
+ POP {r0, lr}
+ BX lr
+
+Note: the Cortex-Mxx requires exception handlers to be thumb labels, this implies bit 0 set.
+To accomplish this, the declaration of the label has to be preceded by the assembler directive
+.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
+be inserted in the correct location in the interrupt vector table. This table is typically
+located in either your runtime startup file or in the tx_initialize_low_level.S file.
+
+
+7. FPU Support
+
+ThreadX for Cortex-Mxx supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context.
+
+
+8. 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:
+
+06-02-2021 Release 6.1.7 changes:
+ tx_thread_secure_stack_initialize.S New file
+ tx_thread_schedule.S Added secure stack initialize to SVC hander
+ tx_thread_secure_stack.c Fixed stack pointer save, initialize in handler mode
+
+04-02-2021 Release 6.1.6 changes:
+ tx_port.h Updated macro definition
+ tx_thread_schedule.s Added low power support
+
+03-02-2021 The following files were changed/added for version 6.1.5:
+ tx_port.h Added ULONG64_DEFINED
+
+09-30-2020 Initial ThreadX 6.1 version for Cortex-Mxx using GNU tools.
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S
new file mode 100644
index 00000000..bb2b34cc
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S
@@ -0,0 +1,283 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+SYSTEM_CLOCK = 6000000
+SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
+
+/* Setup the stack and heap areas. */
+
+STACK_SIZE = 0x00000400
+HEAP_SIZE = 0x00000000
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 01-31-2022 Scott Larson Fixed predefined macro name, */
+/* resulting in version 6.1.10 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_initialize_low_level
+ .thumb_func
+.type _tx_initialize_low_level, function
+_tx_initialize_low_level:
+
+ /* Disable interrupts during ThreadX initialization. */
+ CPSID i
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ LDR r1, =__RAM_segment_used_end__ // Build first free address
+ ADD r1, r1, #4 //
+ STR r1, [r0] // Setup first unused memory pointer
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =_vectors // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Enable the cycle count register. */
+ LDR r0, =0xE0001000 // Build address of DWT register
+ LDR r1, [r0] // Pickup the current value
+ ORR r1, r1, #1 // Set the CYCCNTENA bit
+ STR r1, [r0] // Enable the cycle count register
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =_vectors // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+
+/* Define shells for each of the unused vectors. */
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_BadHandler
+ .thumb_func
+.type __tx_BadHandler, function
+__tx_BadHandler:
+ B __tx_BadHandler
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_IntHandler
+ .thumb_func
+.type __tx_IntHandler, function
+__tx_IntHandler:
+// VOID InterruptHandler (VOID)
+// {
+ PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment)
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ /* Do interrupt handler work here */
+ /* .... */
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0,lr}
+ BX lr
+// }
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global SysTick_Handler
+ .thumb_func
+.type SysTick_Handler, function
+SysTick_Handler:
+// VOID TimerInterruptHandler (VOID)
+// {
+ PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment)
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0,lr}
+ BX lr
+// }
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global HardFault_Handler
+ .thumb_func
+.type HardFault_Handler, function
+HardFault_Handler:
+ B HardFault_Handler
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global UsageFault_Handler
+ .thumb_func
+.type UsageFault_Handler, function
+UsageFault_Handler:
+ CPSID i // Disable interrupts
+ // Check for stack limit fault
+ LDR r0, =0xE000ED28 // CFSR address
+ LDR r1,[r0] // Pick up CFSR
+ TST r1, #0x00100000 // Check for Stack Overflow
+_unhandled_usage_loop:
+ BEQ _unhandled_usage_loop // If not stack overflow then loop
+
+ // Handle stack overflow
+ STR r1, [r0] // Clear CFSR flag(s)
+
+#ifdef __ARM_FP
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Store the value
+#endif
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r0,[r0] // Pick up current thread pointer
+ PUSH {r0,lr} // Save LR (and r0 to maintain stack alignment)
+ BL _tx_thread_stack_error_handler // Call ThreadX/user handler
+ POP {r0,lr} // Restore LR and dummy reg
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ // Call the thread exit function to indicate the thread is no longer executing.
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from UsageFault_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+ CPSIE i // Enable interrupts
+ BX lr // Return from exception
+
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_NMIHandler
+ .thumb_func
+.type __tx_NMIHandler, function
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global __tx_DBGHandler
+ .thumb_func
+.type __tx_DBGHandler, function
+__tx_DBGHandler:
+ B __tx_DBGHandler
+
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_misra.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_misra.S
new file mode 100644
index 00000000..c84d8576
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_misra.S
@@ -0,0 +1,723 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+ #define SHT_PROGBITS 0x1
+
+ .global __aeabi_memset
+ .global _tx_thread_current_ptr
+ .global _tx_thread_interrupt_disable
+ .global _tx_thread_interrupt_restore
+ .global _tx_thread_stack_analyze
+ .global _tx_thread_stack_error_handler
+ .global _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_trace_buffer_current_ptr
+ .global _tx_trace_buffer_end_ptr
+ .global _tx_trace_buffer_start_ptr
+ .global _tx_trace_event_enable_bits
+ .global _tx_trace_full_notify_function
+ .global _tx_trace_header_ptr
+#endif
+
+ .global _tx_misra_always_true
+ .global _tx_misra_block_pool_to_uchar_pointer_convert
+ .global _tx_misra_byte_pool_to_uchar_pointer_convert
+ .global _tx_misra_char_to_uchar_pointer_convert
+ .global _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_indirect_void_to_uchar_pointer_convert
+ .global _tx_misra_memset
+ .global _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_object_to_uchar_pointer_convert
+#endif
+ .global _tx_misra_pointer_to_ulong_convert
+ .global _tx_misra_status_get
+ .global _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_time_stamp_get
+#endif
+ .global _tx_misra_timer_indirect_to_void_pointer_convert
+ .global _tx_misra_timer_pointer_add
+ .global _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_trace_event_insert
+#endif
+ .global _tx_misra_uchar_pointer_add
+ .global _tx_misra_uchar_pointer_dif
+ .global _tx_misra_uchar_pointer_sub
+ .global _tx_misra_uchar_to_align_type_pointer_convert
+ .global _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_entry_pointer_convert
+ .global _tx_misra_uchar_to_header_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ .global _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ .global _tx_misra_uchar_to_object_pointer_convert
+#endif
+ .global _tx_misra_uchar_to_void_pointer_convert
+ .global _tx_misra_ulong_pointer_add
+ .global _tx_misra_ulong_pointer_dif
+ .global _tx_misra_ulong_pointer_sub
+ .global _tx_misra_ulong_to_pointer_convert
+ .global _tx_misra_ulong_to_thread_pointer_convert
+ .global _tx_misra_user_timer_pointer_get
+ .global _tx_misra_void_to_block_pool_pointer_convert
+ .global _tx_misra_void_to_byte_pool_pointer_convert
+ .global _tx_misra_void_to_event_flags_pointer_convert
+ .global _tx_misra_void_to_indirect_uchar_pointer_convert
+ .global _tx_misra_void_to_mutex_pointer_convert
+ .global _tx_misra_void_to_queue_pointer_convert
+ .global _tx_misra_void_to_semaphore_pointer_convert
+ .global _tx_misra_void_to_thread_pointer_convert
+ .global _tx_misra_void_to_uchar_pointer_convert
+ .global _tx_misra_void_to_ulong_pointer_convert
+ .global _tx_misra_ipsr_get
+ .global _tx_misra_control_get
+ .global _tx_misra_control_set
+#ifdef __ARM_FP
+ .global _tx_misra_fpccr_get
+ .global _tx_misra_vfp_touch
+#endif
+
+ .global _tx_misra_event_flags_group_not_used
+ .global _tx_misra_event_flags_set_notify_not_used
+ .global _tx_misra_queue_not_used
+ .global _tx_misra_queue_send_notify_not_used
+ .global _tx_misra_semaphore_not_used
+ .global _tx_misra_semaphore_put_notify_not_used
+ .global _tx_misra_thread_entry_exit_notify_not_used
+ .global _tx_misra_thread_not_used
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .align 4
+ .syntax unified
+ .thumb_func
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ .text
+ .thumb_func
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N _tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N _tx_misra_message_copy_1
+_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N _tx_misra_message_copy_2
+_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR R2,=0x54485244
+ CMP R1,R2
+ BNE.N _tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N _tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N _tx_misra_thread_stack_check_3
+_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N _tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R5,DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N _tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N _tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N _tx_misra_trace_event_insert_2
+_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N _tx_misra_trace_event_insert_4
+ LDR.N R0,DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N _tx_misra_trace_event_insert_0
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N _tx_misra_trace_event_insert_0
+_tx_misra_trace_event_insert_4:
+ LDR.N R0,DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ .data
+DataTable2_1:
+ .word _tx_trace_buffer_current_ptr
+
+ .data
+DataTable2_2:
+ .word _tx_trace_event_enable_bits
+
+ .data
+DataTable2_5:
+ .word _tx_trace_buffer_end_ptr
+
+ .data
+DataTable2_6:
+ .word _tx_trace_buffer_start_ptr
+
+ .data
+DataTable2_7:
+ .word _tx_trace_header_ptr
+
+ .data
+DataTable2_8:
+ .word _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ .data
+DataTable2_3:
+ .word _tx_thread_system_state
+
+ .data
+DataTable2_4:
+ .word _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARM_FP
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ .text
+ .thumb_func
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ .data
+ .word 0
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_restore.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..4c5de879
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_exit
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is not needed for Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_context_restore
+ .thumb_func
+.type _tx_thread_context_restore, function
+_tx_thread_context_restore:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_save.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..9058a806
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ .global _tx_execution_isr_enter
+#endif
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is not needed for Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_context_save
+ .thumb_func
+.type _tx_thread_context_save, function
+_tx_thread_context_save:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_control.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..c55ce306
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ .section .text
+ .balign 4
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_interrupt_control
+ .thumb_func
+.type _tx_thread_interrupt_control, function
+_tx_thread_interrupt_control:
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_disable.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_disable.S
new file mode 100644
index 00000000..27f5894f
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_disable.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_interrupt_disable
+ .thumb_func
+.type _tx_thread_interrupt_disable, function
+_tx_thread_interrupt_disable:
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_restore.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_restore.S
new file mode 100644
index 00000000..29d5cc44
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_interrupt_restore.S
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_interrupt_restore
+ .thumb_func
+.type _tx_thread_interrupt_restore, function
+_tx_thread_interrupt_restore:
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S
new file mode 100644
index 00000000..7ae7c982
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,396 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 04-02-2021 Scott Larson Modified comment(s), added */
+/* low power code, */
+/* resulting in version 6.1.6 */
+/* 06-02-2021 Scott Larson Added secure stack initialize */
+/* in SVC handler, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Scott Larson Fixed predefined macro name, */
+/* resulting in version 6.1.10 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_schedule
+ .thumb_func
+.type _tx_thread_schedule, function
+_tx_thread_schedule:
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __ARM_FP
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global PendSV_Handler
+ .thumb_func
+.type PendSV_Handler, function
+ /* Get current thread value and new thread pointer. */
+PendSV_Handler:
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+ STR r12, [r1, #8] // Save the thread stack pointer
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // Save secure context
+ LDR r5, [r1,#0x90] // Load secure stack index
+ CBZ r5, _skip_secure_save // Skip save if there is no secure context
+ PUSH {r0,r1,r2,r3} // Save scratch registers
+ MOV r0, r1 // Move thread ptr to r0
+ BL _tx_thread_secure_stack_context_save // Save secure stack
+ POP {r0,r1,r2,r3} // Restore secure registers
+_skip_secure_save:
+#endif
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // Restore secure context
+ LDR r0, [r1,#0x90] // Load secure stack index
+ CBZ r0, _skip_secure_restore // Skip restore if there is no secure context
+ PUSH {r0,r1} // Save r1 (and dummy r0)
+ MOV r0, r1 // Move thread ptr to r0
+ BL _tx_thread_secure_stack_context_restore // Restore secure stack
+ POP {r0,r1} // Restore r1 (and dummy r0)
+_skip_secure_restore:
+#endif
+
+ /* Restore the thread context and PSP. */
+ LDR r12, [r1, #12] // Get stack start
+ MSR PSPLIM, r12 // Set stack limit
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARM_FP
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // SVC_Handler is not needed when ThreadX is running in single mode.
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global SVC_Handler
+ .thumb_func
+.type SVC_Handler, function
+SVC_Handler:
+ TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2
+ ITE EQ
+ MRSEQ r0, MSP // Get MSP if return stack is MSP
+ MRSNE r0, PSP // Get PSP if return stack is PSP
+
+ LDR r1, [r0,#24] // Load saved PC from stack
+ LDRB r1, [r1,#-2] // Load SVC number
+
+ CMP r1, #1 // Is it a secure stack allocate request?
+ BEQ _tx_svc_secure_alloc // Yes, go there
+
+ CMP r1, #2 // Is it a secure stack free request?
+ BEQ _tx_svc_secure_free // Yes, go there
+
+ CMP r1, #3 // Is it a secure stack init request?
+ BEQ _tx_svc_secure_init // Yes, go there
+
+ // Unknown SVC argument - just return
+ BX lr
+
+_tx_svc_secure_alloc:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ LDM r0, {r0-r3} // Load function parameters from stack
+ BL _tx_thread_secure_mode_stack_allocate
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ STR r0,[r12] // Store function return value
+ BX lr
+_tx_svc_secure_free:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ LDM r0, {r0-r3} // Load function parameters from stack
+ BL _tx_thread_secure_mode_stack_free
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ STR r0,[r12] // Store function return value
+ BX lr
+_tx_svc_secure_init:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ BL _tx_thread_secure_mode_stack_initialize
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ BX lr
+#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE
+
+
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_vfp_access
+ .thumb_func
+.type _tx_vfp_access, function
+_tx_vfp_access:
+#if TX_ENABLE_FPU_SUPPORT
+ VMOV.F32 s0, s0 // Simply access the VFP
+#endif
+ BX lr // Return to caller
+.end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack.c b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack.c
new file mode 100644
index 00000000..cbd30fa5
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack.c
@@ -0,0 +1,596 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "tx_api.h"
+
+/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined,
+ no secure stack functionality is needed. */
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+
+#define TX_SOURCE_CODE
+
+#include "tx_secure_interface.h" /* Interface for NS code. */
+
+/* Minimum size of secure stack. */
+#ifndef TX_THREAD_SECURE_STACK_MINIMUM
+#define TX_THREAD_SECURE_STACK_MINIMUM 256
+#endif
+/* Maximum size of secure stack. */
+#ifndef TX_THREAD_SECURE_STACK_MAXIMUM
+#define TX_THREAD_SECURE_STACK_MAXIMUM 1024
+#endif
+
+/* 8 bytes added to stack size to "seal" stack. */
+#define TX_THREAD_STACK_SEAL_SIZE 8
+#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5
+
+/* max number of Secure context */
+#ifndef TX_MAX_SECURE_CONTEXTS
+#define TX_MAX_SECURE_CONTEXTS 32
+#endif
+#define TX_INVALID_SECURE_CONTEXT_IDX (-1)
+
+/* Secure stack info struct to hold stack start, stack limit,
+ current stack pointer, and pointer to owning thread.
+ This will be allocated for each thread with a secure stack. */
+typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
+{
+ VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */
+ VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */
+ VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */
+ TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */
+ INT tx_next_free_index; /* Next free index of free secure context */
+} TX_THREAD_SECURE_STACK_INFO;
+
+/* Static secure contexts */
+static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS];
+/* Head of free secure context */
+static INT tx_head_free_index = 0U;
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_initialize Cortex-Mxx/GNU */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes secure mode to use PSP stack. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 06-02-2021 Scott Larson Change name, execute in */
+/* handler mode, */
+/* disable optimizations, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry, optimize(0)))
+UINT _tx_thread_secure_mode_stack_initialize(void)
+{
+UINT status;
+ULONG control;
+ULONG ipsr;
+INT index;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+ /* Set secure mode to use PSP. */
+ 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. */
+ asm volatile("MSR PSPLIM, %0" :: "r" (0));
+ asm volatile("MSR PSP, %0" :: "r" (0));
+
+ for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++)
+ {
+
+ /* Check last index and mark next free to invalid index */
+ if(index == (TX_MAX_SECURE_CONTEXTS - 1))
+ {
+ tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+ else
+ {
+ tx_thread_secure_context[index].tx_next_free_index = index + 1;
+ }
+ }
+
+ status = TX_SUCCESS;
+ }
+ return status;
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_allocate Cortex-Mxx/GNU */
+/* 6.1.11a */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allocates a thread's secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of stack to allocates */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_SIZE_ERROR Invalid stack size */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* malloc Compiler's malloc function */
+/* */
+/* CALLED BY */
+/* */
+/* SVC Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* added stack sealing, */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* 05-02-2022 Scott Larson Modified comment(s), added */
+/* TX_INTERRUPT_SAVE_AREA, */
+/* resulting in version 6.1.11a*/
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+UCHAR *stack_mem;
+ULONG ipsr;
+ULONG psplim_ns;
+INT secure_context_index;
+
+ status = TX_SUCCESS;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+ else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM)
+ {
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Check if thread already has secure stack allocated. */
+ else if (thread_ptr -> tx_thread_secure_stack_context != 0)
+ {
+ status = TX_THREAD_ERROR;
+ }
+
+ else
+ {
+ TX_DISABLE
+
+ /* Allocate free index for secure stack info. */
+ if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX)
+ {
+ secure_context_index = tx_head_free_index;
+ tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index;
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+ else
+ {
+ secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+
+ TX_RESTORE
+
+ if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX)
+ {
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* If stack info allocated, allocate a stack & seal. */
+ stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE);
+
+ if(stack_mem != TX_NULL)
+ {
+ /* Secure stack has been allocated, save in the stack info struct. */
+ info_ptr -> tx_thread_secure_stack_limit = stack_mem;
+ info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size;
+ info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start;
+ info_ptr -> tx_thread_ptr = thread_ptr;
+
+ /* Seal bottom of stack. */
+ *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE;
+
+ /* Save secure context id (i.e non-zero base index) in thread. */
+ thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1);
+
+ /* 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. */
+ 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)));
+ }
+ }
+
+ else
+ {
+ TX_DISABLE
+
+ /* Stack not allocated, free the info struct. */
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
+ tx_head_free_index = secure_context_index;
+ TX_RESTORE
+
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ else
+ {
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ return(status);
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_free Cortex-Mxx/GNU */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function frees a thread's secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* free Compiler's free() function */
+/* */
+/* CALLED BY */
+/* */
+/* SVC Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+ULONG ipsr;
+INT secure_context_index;
+
+ status = TX_SUCCESS;
+
+ /* Pickup stack info id from thread. */
+ secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Pickup stack info from static array of secure contexts. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ status = TX_THREAD_ERROR;
+ }
+
+ else
+ {
+
+ /* Free secure stack. */
+ free(info_ptr -> tx_thread_secure_stack_limit);
+
+ TX_DISABLE
+
+ /* Free info struct. */
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
+ tx_head_free_index = secure_context_index;
+ TX_RESTORE
+
+ /* Clear secure context from thread. */
+ thread_ptr -> tx_thread_secure_stack_context = 0;
+ }
+ }
+
+ return(status);
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_context_save Cortex-Mxx/GNU */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves context of the secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* PendSV Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 06-02-2021 Scott Larson Fix stack pointer save, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr)
+{
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+ULONG sp;
+ULONG ipsr;
+INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* This function should be called from scheduler only. */
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
+ {
+ return;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ return;
+ }
+
+ /* Pickup the secure context pointer. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ return;
+ }
+
+ /* Check that stack pointer is in range */
+ 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))
+ {
+ return;
+ }
+
+ /* Save stack pointer. */
+ info_ptr -> tx_thread_secure_stack_ptr = (VOID *) 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. */
+ asm volatile("MSR PSPLIM, %0" :: "r" (0));
+ asm volatile("MSR PSP, %0" :: "r" (0));
+
+ return;
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_context_restore Cortex-Mxx/GNU */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function restores context of the secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* PendSV Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr)
+{
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+ULONG ipsr;
+INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* This function should be called from scheduler only. */
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
+ {
+ return;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ return;
+ }
+
+ /* Pickup the secure context pointer. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ return;
+ }
+
+ /* Set stack pointer and limit. */
+ 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;
+}
+
+#endif
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_allocate.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_allocate.S
new file mode 100644
index 00000000..408e7805
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_allocate.S
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_allocate Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to allocate a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of secure stack to */
+/* allocate */
+/* */
+/* OUTPUT */
+/* */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* SVC 1 */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_secure_stack_allocate
+ .thumb_func
+.type _tx_thread_secure_stack_allocate, function
+_tx_thread_secure_stack_allocate:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ MRS r3, PRIMASK // Save interrupt mask
+ CPSIE i // Enable interrupts for SVC call
+ SVC 1
+ CMP r3, #0 // If interrupts enabled, just return
+ BEQ _alloc_return_interrupt_enabled
+ CPSID i // Otherwise, disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+_alloc_return_interrupt_enabled:
+ BX lr
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_free.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_free.S
new file mode 100644
index 00000000..7b33d795
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_free.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_free Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to free a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* SVC 2 */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_secure_stack_free
+ .thumb_func
+.type _tx_thread_secure_stack_free, function
+_tx_thread_secure_stack_free:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ MRS r3, PRIMASK // Save interrupt mask
+ CPSIE i // Enable interrupts for SVC call
+ SVC 2
+ CMP r3, #0 // If interrupts enabled, just return
+ BEQ _free_return_interrupt_enabled
+ CPSID i // Otherwise, disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+_free_return_interrupt_enabled:
+ BX lr
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_initialize.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_initialize.S
new file mode 100644
index 00000000..8566d4b2
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_secure_stack_initialize.S
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_initialize Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to initialize a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* none */
+/* */
+/* OUTPUT */
+/* */
+/* none */
+/* */
+/* CALLS */
+/* */
+/* SVC 3 */
+/* */
+/* CALLED BY */
+/* */
+/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 07-29-2022 Scott Larson Modified comments and changed */
+/* secure stack initialization */
+/* macro to port-specific, */
+/* resulting in version 6.1.12 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_secure_stack_initialize(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_secure_stack_initialize
+ .thumb_func
+.type _tx_thread_secure_stack_initialize, function
+_tx_thread_secure_stack_initialize:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ CPSIE i // Enable interrupts for SVC call
+ SVC 3
+ CPSID i // Disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+ BX lr
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_stack_build.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..5322c89b
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,145 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_stack_build
+ .thumb_func
+.type _tx_thread_stack_build, function
+_tx_thread_stack_build:
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+#ifdef TX_SINGLE_MODE_SECURE
+ LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode
+#else
+ LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP
+#endif
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S
new file mode 100644
index 00000000..bd9c84ba
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S
@@ -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 */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_thread_system_return
+ .thumb_func
+.type _tx_thread_system_return, function
+_tx_thread_system_return:
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context:
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_timer_interrupt.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..68436d86
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,248 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+#include "tx_user.h"
+#endif
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mxx/GNU */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-08-2023 Scott Larson Include tx_user.h, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+ .section .text
+ .balign 4
+ .syntax unified
+ .eabi_attribute Tag_ABI_align_preserved, 1
+ .global _tx_timer_interrupt
+ .thumb_func
+.type _tx_timer_interrupt, function
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ PUSH {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ POP {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+ .end
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_allocate.c b/ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_allocate.c
new file mode 100644
index 00000000..caa47139
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_allocate.c
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_allocate Cortex-Mxx */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the secure stack allocate */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of secure stack to */
+/* allocate */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_secure_stack_allocate Actual stack alloc function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+{
+#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE)
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+UINT status;
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+ /* Is call from an interrupt and not initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+ /* Call actual secure stack allocate function. */
+ status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size);
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_free.c b/ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_free.c
new file mode 100644
index 00000000..0e1efcf4
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/gnu/src/txe_thread_secure_stack_free.c
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_thread_secure_stack_free Cortex-Mxx */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the secure stack free */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_secure_stack_free Actual stack free function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr)
+{
+#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE)
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+UINT status;
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+ /* Is call from an interrupt and not initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual secure stack allocate function. */
+ status = _tx_thread_secure_stack_free(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
diff --git a/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt b/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt
new file mode 100644
index 00000000..122b41ef
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt
@@ -0,0 +1,221 @@
+ Microsoft's Azure RTOS ThreadX for Cortex-Mxx
+
+ Using the IAR Tools
+
+
+1. Building the ThreadX run-time Library
+
+Import all ThreadX common and port-specific source files into an IAR project.
+Configure the project to build a library rather than an executable. This
+results in the ThreadX run-time library file tx.a, which is needed by
+the application.
+Files tx_thread_stack_error_handler.c and tx_thread_stack_error_notify.c
+replace the common files of the same name.
+
+2. Demonstration System
+
+No demonstration is provided because the IAR EWARM 8.50 simulator does
+not simulate the Cortex-Mxx correctly.
+
+
+3. System Initialization
+
+The entry point in ThreadX for the Cortex-Mxx using IAR tools is at label
+__iar_program_start. This is defined within the IAR compiler's startup code.
+In addition, this is where all static and global preset C variable
+initialization processing takes place.
+
+The ThreadX tx_initialize_low_level.s file is responsible for setting up
+various system data structures, and a periodic timer interrupt source.
+
+The _tx_initialize_low_level function inside of tx_initialize_low_level.s
+also 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. To accomplish this, a section is created in
+tx_initialize_low_level.s called FREE_MEM, which must be located after all
+other RAM sections in memory.
+
+
+4. Register Usage and Stack Frames
+
+The following defines the saved context stack frames for context switches
+that occur as a result of interrupt handling or from thread-level API calls.
+All suspended threads have the same stack frame in the Cortex-Mxx version of
+ThreadX. The top of the suspended thread's stack is pointed to by
+tx_thread_stack_ptr in the associated thread control block TX_THREAD.
+
+Non-FPU Stack Frame:
+
+ Stack Offset Stack Contents
+
+ 0x00 LR Interrupted LR (LR at time of PENDSV)
+ 0x04 r4 Software stacked GP registers
+ 0x08 r5
+ 0x0C r6
+ 0x10 r7
+ 0x14 r8
+ 0x18 r9
+ 0x1C r10
+ 0x20 r11
+ 0x24 r0 Hardware stacked registers
+ 0x28 r1
+ 0x2C r2
+ 0x30 r3
+ 0x34 r12
+ 0x38 lr
+ 0x3C pc
+ 0x40 xPSR
+
+FPU Stack Frame (only interrupted thread with FPU enabled):
+
+ Stack Offset Stack Contents
+
+ 0x00 LR Interrupted LR (LR at time of PENDSV)
+ 0x04 s16 Software stacked FPU registers
+ 0x08 s17
+ 0x0C s18
+ 0x10 s19
+ 0x14 s20
+ 0x18 s21
+ 0x1C s22
+ 0x20 s23
+ 0x24 s24
+ 0x28 s25
+ 0x2C s26
+ 0x30 s27
+ 0x34 s28
+ 0x38 s29
+ 0x3C s30
+ 0x40 s31
+ 0x44 r4 Software stacked registers
+ 0x48 r5
+ 0x4C r6
+ 0x50 r7
+ 0x54 r8
+ 0x58 r9
+ 0x5C r10
+ 0x60 r11
+ 0x64 r0 Hardware stacked registers
+ 0x68 r1
+ 0x6C r2
+ 0x70 r3
+ 0x74 r12
+ 0x78 lr
+ 0x7C pc
+ 0x80 xPSR
+ 0x84 s0 Hardware stacked FPU registers
+ 0x88 s1
+ 0x8C s2
+ 0x90 s3
+ 0x94 s4
+ 0x98 s5
+ 0x9C s6
+ 0xA0 s7
+ 0xA4 s8
+ 0xA8 s9
+ 0xAC s10
+ 0xB0 s11
+ 0xB4 s12
+ 0xB8 s13
+ 0xBC s14
+ 0xC0 s15
+ 0xC4 fpscr
+
+
+5. Improving Performance
+
+To make ThreadX and the application(s) run faster, you can enable
+all compiler 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.
+
+
+6. Interrupt Handling
+
+The Cortex-Mxx vectors start at the label __vector_table and is typically defined in a
+startup.s file (or similar). The application may modify the vector area according to its needs.
+
+
+6.1 Managed Interrupts
+
+ISRs for Cortex-M using the IAR tools can be written completely in C (or assembly
+language) without any calls to _tx_thread_context_save or _tx_thread_context_restore.
+These ISRs are allowed access to the ThreadX API that is available to ISRs.
+
+ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
+
+void your_C_isr(void)
+{
+
+ /* ISR processing goes here, including any needed function calls. */
+}
+
+ISRs written in assembly language will take the form:
+
+ PUBLIC your_assembly_isr
+your_assembly_isr:
+
+ PUSH {r0, lr}
+
+ ; ISR processing goes here, including any needed function calls.
+
+ POP {r0, lr}
+ BX lr
+
+
+7. IAR Thread-safe Library Support
+
+Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
+and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
+should have the following line added (if not already in place):
+
+initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
+
+
+7. IAR Thread-safe Library Support
+
+Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
+and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
+should have the following line added (if not already in place):
+
+initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
+
+The project options "General Options -> Library Configuration" should also have the
+"Enable thread support in library" box selected.
+
+
+8. VFP Support
+
+ThreadX for Cortex-Mxx supports automatic ("lazy") VFP support, which means that applications threads
+can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
+context.
+
+
+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:
+
+06-02-2021 Release 6.1.7 changes:
+ tx_thread_secure_stack_initialize.s New file
+ tx_thread_schedule.s Added secure stack initialize to SVC hander
+ tx_thread_secure_stack.c Fixed stack pointer save, initialize in handler mode
+
+04-02-2021 Release 6.1.6 changes:
+ tx_port.h Updated macro definition
+ tx_thread_schedule.s Added low power support
+
+03-02-2021 The following files were changed/added for version 6.1.5:
+ tx_port.h Added ULONG64_DEFINED
+
+09-30-2020 Initial ThreadX 6.1 version for Cortex-Mxx using IAR's ARM tools.
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c b/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c
new file mode 100644
index 00000000..dd719370
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c
@@ -0,0 +1,804 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** IAR Multithreaded Library Support */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Define IAR library for tools prior to version 8. */
+
+#if (__VER__ < 8000000)
+
+
+/* IAR version 7 and below. */
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/* This implementation requires that the following macros are defined in the
+ tx_port.h file and <yvals.h> is included with the following code segments:
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+ This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
+ application.
+
+ Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
+*/
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+
+#include <yvals.h>
+
+
+#if _MULTI_THREAD
+
+TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
+UINT __tx_iar_system_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_system_lock_no_mutexes;
+UINT __tx_iar_system_lock_internal_errors;
+UINT __tx_iar_system_lock_isr_caller;
+
+
+/* Define the TLS access function for the IAR library. */
+
+void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
+{
+
+char _DLIB_TLS_MEMORY *p = 0;
+
+ /* Is there a current thread? */
+ if (_tx_thread_current_ptr)
+ p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
+ else
+ p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
+ p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
+ return (void _DLIB_TLS_MEMORY *) p;
+}
+
+
+/* Define mutexes for IAR library. */
+
+void __iar_system_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_LOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_system_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_system_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_system_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+}
+
+
+#if _DLIB_FILE_DESCRIPTOR
+
+TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
+UINT __tx_iar_file_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_file_lock_no_mutexes;
+UINT __tx_iar_file_lock_internal_errors;
+UINT __tx_iar_file_lock_isr_caller;
+
+
+void __iar_file_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_FLOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_file_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_file_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_file_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+#endif /* _DLIB_FILE_DESCRIPTOR */
+
+#endif /* _MULTI_THREAD */
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#else /* IAR version 8 and above. */
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+/* This implementation requires that the following macros are defined in the
+ tx_port.h file and <yvals.h> is included with the following code segments:
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#else
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+void *_tx_iar_create_per_thread_tls_area(void);
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+void __iar_Initlocks(void);
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
+#else
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+
+ This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
+ application.
+
+ Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
+*/
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+
+#include <DLib_threads.h>
+
+
+void * __aeabi_read_tp();
+
+void* _tx_iar_create_per_thread_tls_area();
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+
+#pragma section="__iar_tls$$DATA"
+
+/* Define the TLS access function for the IAR library. */
+void * __aeabi_read_tp(void)
+{
+ void *p = 0;
+ TX_THREAD *thread_ptr = _tx_thread_current_ptr;
+ if (thread_ptr)
+ {
+ p = thread_ptr->tx_thread_iar_tls_pointer;
+ }
+ else
+ {
+ p = __section_begin("__iar_tls$$DATA");
+ }
+ return p;
+}
+
+/* Define the TLS creation and destruction to use malloc/free. */
+
+void* _tx_iar_create_per_thread_tls_area()
+{
+ UINT tls_size = __iar_tls_size();
+
+ /* Get memory for TLS. */
+ void *p = malloc(tls_size);
+
+ /* Initialize TLS-area and run constructors for objects in TLS */
+ __iar_tls_init(p);
+ return p;
+}
+
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
+{
+ /* Destroy objects living in TLS */
+ __call_thread_dtors();
+ free(tls_ptr);
+}
+
+#ifndef _MAX_LOCK
+#define _MAX_LOCK 4
+#endif
+
+static TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
+static UINT __tx_iar_system_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_system_lock_no_mutexes;
+UINT __tx_iar_system_lock_internal_errors;
+UINT __tx_iar_system_lock_isr_caller;
+
+
+/* Define mutexes for IAR library. */
+
+void __iar_system_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_LOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_system_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_system_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_system_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *m)
+{
+ if (*m)
+ {
+ UINT status;
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+ }
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *m)
+{
+ if (*m)
+ {
+ UINT status;
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_system_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_system_lock_isr_caller++;
+ }
+ }
+}
+
+
+#if _DLIB_FILE_DESCRIPTOR
+
+#include <stdio.h> /* Added to get access to FOPEN_MAX */
+#ifndef _MAX_FLOCK
+#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */
+#endif
+
+
+TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
+UINT __tx_iar_file_lock_next_free_mutex = 0;
+
+
+/* Define error counters, just for debug purposes. */
+
+UINT __tx_iar_file_lock_no_mutexes;
+UINT __tx_iar_file_lock_internal_errors;
+UINT __tx_iar_file_lock_isr_caller;
+
+
+void __iar_file_Mtxinit(__iar_Rmtx *m)
+{
+
+UINT i;
+UINT status;
+TX_MUTEX *mutex_ptr;
+
+
+ /* First, find a free mutex in the list. */
+ for (i = 0; i < _MAX_FLOCK; i++)
+ {
+
+ /* Setup a pointer to the start of the next free mutex. */
+ mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
+
+ /* Check for wrap-around on the next free mutex. */
+ if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
+ {
+
+ /* Yes, set the free index back to 0. */
+ __tx_iar_file_lock_next_free_mutex = 0;
+ }
+
+ /* Is this mutex free? */
+ if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
+ {
+
+ /* Yes, this mutex is free, get out of the loop! */
+ break;
+ }
+ }
+
+ /* Determine if a free mutex was found. */
+ if (i >= _MAX_LOCK)
+ {
+
+ /* Error! No more free mutexes! */
+
+ /* Increment the no mutexes error counter. */
+ __tx_iar_file_lock_no_mutexes++;
+
+ /* Set return pointer to NULL. */
+ *m = TX_NULL;
+
+ /* Return. */
+ return;
+ }
+
+ /* Now create the ThreadX mutex for the IAR library. */
+ status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
+
+ /* Determine if the creation was successful. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Yes, successful creation, return mutex pointer. */
+ *m = (VOID *) mutex_ptr;
+ }
+ else
+ {
+
+ /* Increment the internal error counter. */
+ __tx_iar_file_lock_internal_errors++;
+
+ /* Return a NULL pointer to indicate an error. */
+ *m = TX_NULL;
+ }
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *m)
+{
+
+ /* Simply delete the mutex. */
+ _tx_mutex_delete((TX_MUTEX *) *m);
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex locks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Get the mutex. */
+ status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *m)
+{
+
+UINT status;
+
+
+ /* Determine the caller's context. Mutex unlocks are only available from initialization and
+ threads. */
+ if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
+ {
+
+ /* Release the mutex. */
+ status = _tx_mutex_put((TX_MUTEX *) *m);
+
+ /* Check the status of the mutex release. */
+ if (status)
+ {
+
+ /* Internal error, increment the counter. */
+ __tx_iar_file_lock_internal_errors++;
+ }
+ }
+ else
+ {
+
+ /* Increment the ISR caller error. */
+ __tx_iar_file_lock_isr_caller++;
+ }
+}
+#endif /* _DLIB_FILE_DESCRIPTOR */
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#endif /* IAR version 8 and above. */
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s
new file mode 100644
index 00000000..7580309e
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s
@@ -0,0 +1,237 @@
+/**************************************************************************/
+/* */
+/* 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_thread_system_stack_ptr
+ EXTERN _tx_initialize_unused_memory
+ EXTERN _tx_timer_interrupt
+ EXTERN __main
+ EXTERN __vector_table
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_stack_error_handler
+
+SYSTEM_CLOCK EQU 96000000
+SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 100) -1)
+
+ RSEG FREE_MEM:DATA
+ PUBLIC __tx_free_memory_start
+__tx_free_memory_start
+ DS32 4
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ PUBLIC _tx_initialize_low_level
+_tx_initialize_low_level:
+
+ /* Disable interrupts during ThreadX initialization. */
+ CPSID i
+
+ /* Set base of available memory to end of non-initialised RAM area. */
+ LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
+ LDR r1, =__tx_free_memory_start // Build first free address
+ STR r1, [r0] // Setup first unused memory pointer
+
+ /* Setup Vector Table Offset Register. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =__vector_table // Pickup address of vector table
+ STR r1, [r0, #0xD08] // Set vector table address
+
+ /* Enable the cycle count register. */
+// LDR r0, =0xE0001000 // Build address of DWT register
+// LDR r1, [r0] // Pickup the current value
+// ORR r1, r1, #1 // Set the CYCCNTENA bit
+// STR r1, [r0] // Enable the cycle count register
+
+ /* Set system stack pointer from vector value. */
+ LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
+ LDR r1, =__vector_table // Pickup address of vector table
+ LDR r1, [r1] // Pickup reset stack pointer
+ STR r1, [r0] // Save system stack pointer
+
+ /* Configure SysTick. */
+ MOV r0, #0xE000E000 // Build address of NVIC registers
+ LDR r1, =SYSTICK_CYCLES
+ STR r1, [r0, #0x14] // Setup SysTick Reload Value
+ MOV r1, #0x7 // Build SysTick Control Enable Value
+ STR r1, [r0, #0x10] // Setup SysTick Control
+
+ /* Configure handler priorities. */
+ LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
+ STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
+ LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
+ STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
+ // Note: SVC must be lowest priority, which is 0xFF
+ LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
+ STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
+ // Note: PnSV must be lowest priority, which is 0xFF
+
+ /* Return to caller. */
+ BX lr
+// }
+
+
+/* Define shells for each of the unused vectors. */
+
+ PUBLIC __tx_BadHandler
+__tx_BadHandler:
+ B __tx_BadHandler
+
+
+ PUBLIC __tx_IntHandler
+__tx_IntHandler:
+// VOID InterruptHandler (VOID)
+// {
+ PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment)
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ /* Do interrupt handler work here */
+ /* .... */
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0,lr}
+ BX lr
+// }
+
+
+ PUBLIC __tx_SysTickHandler
+ PUBLIC SysTick_Handler
+SysTick_Handler:
+__tx_SysTickHandler:
+// VOID TimerInterruptHandler (VOID)
+// {
+ PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment)
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_enter // Call the ISR enter function
+#endif
+ BL _tx_timer_interrupt
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+ POP {r0,lr}
+ BX lr
+// }
+
+ PUBLIC HardFault_Handler
+HardFault_Handler:
+ B HardFault_Handler
+
+
+ PUBLIC UsageFault_Handler
+UsageFault_Handler:
+ CPSID i // Disable interrupts
+ // Check for stack limit fault
+ LDR r0, =0xE000ED28 // CFSR address
+ LDR r1,[r0] // Pick up CFSR
+ TST r1, #0x00100000 // Check for Stack Overflow
+_unhandled_usage_loop
+ BEQ _unhandled_usage_loop // If not stack overflow then loop
+
+ // Handle stack overflow
+ STR r1, [r0] // Clear CFSR flag(s)
+
+#ifdef __ARMVFP__
+ LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
+ LDR r1, [r0] // Load FPCCR
+ BIC r1, r1, #1 // Clear the lazy preservation active bit
+ STR r1, [r0] // Store the value
+#endif
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r0,[r0] // Pick up current thread pointer
+ PUSH {r0,lr} // Save LR (and r0 to maintain stack alignment)
+ BL _tx_thread_stack_error_handler // Call ThreadX/user handler
+ POP {r0,lr} // Restore LR and dummy reg
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ // Call the thread exit function to indicate the thread is no longer executing.
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#endif
+
+ MOV r1, #0 // Build NULL value
+ LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
+ STR r1, [r0] // Clear current thread pointer
+
+ // Return from UsageFault_Handler exception
+ LDR r0, =0xE000ED04 // Load ICSR
+ LDR r1, =0x10000000 // Set PENDSVSET bit
+ STR r1, [r0] // Store ICSR
+ DSB // Wait for memory access to complete
+ CPSIE i // Enable interrupts
+ BX lr // Return from exception
+
+
+ PUBLIC __tx_NMIHandler
+__tx_NMIHandler:
+ B __tx_NMIHandler
+
+
+ PUBLIC __tx_DBGHandler
+__tx_DBGHandler:
+ B __tx_DBGHandler
+
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_misra.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_misra.s
new file mode 100644
index 00000000..ab3fef69
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_misra.s
@@ -0,0 +1,763 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** ThreadX MISRA Compliance */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ #define SHT_PROGBITS 0x1
+
+ EXTERN __aeabi_memset
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_interrupt_disable
+ EXTERN _tx_thread_interrupt_restore
+ EXTERN _tx_thread_stack_analyze
+ EXTERN _tx_thread_stack_error_handler
+ EXTERN _tx_thread_system_state
+#ifdef TX_ENABLE_EVENT_TRACE
+ EXTERN _tx_trace_buffer_current_ptr
+ EXTERN _tx_trace_buffer_end_ptr
+ EXTERN _tx_trace_buffer_start_ptr
+ EXTERN _tx_trace_event_enable_bits
+ EXTERN _tx_trace_full_notify_function
+ EXTERN _tx_trace_header_ptr
+#endif
+
+ PUBLIC _tx_misra_always_true
+ PUBLIC _tx_misra_block_pool_to_uchar_pointer_convert
+ PUBLIC _tx_misra_byte_pool_to_uchar_pointer_convert
+ PUBLIC _tx_misra_char_to_uchar_pointer_convert
+ PUBLIC _tx_misra_const_char_to_char_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_entry_to_uchar_pointer_convert
+#endif
+ PUBLIC _tx_misra_indirect_void_to_uchar_pointer_convert
+ PUBLIC _tx_misra_memset
+ PUBLIC _tx_misra_message_copy
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_object_to_uchar_pointer_convert
+#endif
+ PUBLIC _tx_misra_pointer_to_ulong_convert
+ PUBLIC _tx_misra_status_get
+ PUBLIC _tx_misra_thread_stack_check
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_time_stamp_get
+#endif
+ PUBLIC _tx_misra_timer_indirect_to_void_pointer_convert
+ PUBLIC _tx_misra_timer_pointer_add
+ PUBLIC _tx_misra_timer_pointer_dif
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_trace_event_insert
+#endif
+ PUBLIC _tx_misra_uchar_pointer_add
+ PUBLIC _tx_misra_uchar_pointer_dif
+ PUBLIC _tx_misra_uchar_pointer_sub
+ PUBLIC _tx_misra_uchar_to_align_type_pointer_convert
+ PUBLIC _tx_misra_uchar_to_block_pool_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_uchar_to_entry_pointer_convert
+ PUBLIC _tx_misra_uchar_to_header_pointer_convert
+#endif
+ PUBLIC _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
+ PUBLIC _tx_misra_uchar_to_indirect_uchar_pointer_convert
+#ifdef TX_ENABLE_EVENT_TRACE
+ PUBLIC _tx_misra_uchar_to_object_pointer_convert
+#endif
+ PUBLIC _tx_misra_uchar_to_void_pointer_convert
+ PUBLIC _tx_misra_ulong_pointer_add
+ PUBLIC _tx_misra_ulong_pointer_dif
+ PUBLIC _tx_misra_ulong_pointer_sub
+ PUBLIC _tx_misra_ulong_to_pointer_convert
+ PUBLIC _tx_misra_ulong_to_thread_pointer_convert
+ PUBLIC _tx_misra_user_timer_pointer_get
+ PUBLIC _tx_misra_void_to_block_pool_pointer_convert
+ PUBLIC _tx_misra_void_to_byte_pool_pointer_convert
+ PUBLIC _tx_misra_void_to_event_flags_pointer_convert
+ PUBLIC _tx_misra_void_to_indirect_uchar_pointer_convert
+ PUBLIC _tx_misra_void_to_mutex_pointer_convert
+ PUBLIC _tx_misra_void_to_queue_pointer_convert
+ PUBLIC _tx_misra_void_to_semaphore_pointer_convert
+ PUBLIC _tx_misra_void_to_thread_pointer_convert
+ PUBLIC _tx_misra_void_to_uchar_pointer_convert
+ PUBLIC _tx_misra_void_to_ulong_pointer_convert
+ PUBLIC _tx_misra_ipsr_get
+ PUBLIC _tx_misra_control_get
+ PUBLIC _tx_misra_control_set
+#ifdef __ARMVFP__
+ PUBLIC _tx_misra_fpccr_get
+ PUBLIC _tx_misra_vfp_touch
+#endif
+
+ PUBLIC _tx_misra_event_flags_group_not_used
+ PUBLIC _tx_misra_event_flags_set_notify_not_used
+ PUBLIC _tx_misra_queue_not_used
+ PUBLIC _tx_misra_queue_send_notify_not_used
+ PUBLIC _tx_misra_semaphore_not_used
+ PUBLIC _tx_misra_semaphore_put_notify_not_used
+ PUBLIC _tx_misra_thread_entry_exit_notify_not_used
+ PUBLIC _tx_misra_thread_not_used
+
+#ifdef TX_MISRA_ENABLE
+ PUBLIC _tx_version_id
+
+ SECTION `.data`:DATA:REORDER:NOROOT(2)
+ DATA
+// 51 CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.1 MISRA C Compliant *";
+_tx_version_id:
+ DC8 43H, 6FH, 70H, 79H, 72H, 69H, 67H, 68H
+ DC8 74H, 20H, 28H, 63H, 29H, 20H, 31H, 39H
+ DC8 39H, 36H, 2DH, 32H, 30H, 31H, 38H, 20H
+ DC8 45H, 78H, 70H, 72H, 65H, 73H, 73H, 20H
+ DC8 4CH, 6FH, 67H, 69H, 63H, 20H, 49H, 6EH
+ DC8 63H, 2EH, 20H, 2AH, 20H, 54H, 68H, 72H
+ DC8 65H, 61H, 64H, 58H, 20H, 36H, 2EH, 31H
+ DC8 20H, 4DH, 49H, 53H, 52H, 41H, 20H, 43H
+ DC8 20H, 43H, 6FH, 6DH, 70H, 6CH, 69H, 61H
+ DC8 6EH, 74H, 20H, 2AH, 0
+ DC8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+#endif //TX_MISRA_ENABLE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_memset:
+ PUSH {R4,LR}
+ MOVS R4,R0
+ MOVS R0,R2
+ MOVS R2,R1
+ MOVS R1,R0
+ MOVS R0,R4
+ BL __aeabi_memset
+ POP {R4,PC} // return
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_add:
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_sub:
+ RSBS R1,R1,#+0
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_uchar_pointer_dif:
+ SUBS R0,R0,R1
+ BX LR // return
+
+
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+/** */
+/** This single function serves all of the below prototypes. */
+/** */
+/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
+/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
+/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
+/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
+/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
+/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
+/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
+/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
+/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
+/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
+/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
+/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
+/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
+/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
+/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
+/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
+/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
+/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
+/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
+/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
+/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
+/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
+/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
+/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
+/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
+/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
+/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
+/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
+/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
+/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
+/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
+/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
+/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
+/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
+/** */
+/************************************************************************************************************************************/
+/************************************************************************************************************************************/
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_pointer_to_ulong_convert:
+_tx_misra_ulong_to_pointer_convert:
+_tx_misra_indirect_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_indirect_uchar_pointer_convert:
+_tx_misra_block_pool_to_uchar_pointer_convert:
+_tx_misra_void_to_block_pool_pointer_convert:
+_tx_misra_void_to_uchar_pointer_convert:
+_tx_misra_uchar_to_block_pool_pointer_convert:
+_tx_misra_void_to_indirect_uchar_pointer_convert:
+_tx_misra_void_to_byte_pool_pointer_convert:
+_tx_misra_byte_pool_to_uchar_pointer_convert:
+_tx_misra_uchar_to_align_type_pointer_convert:
+_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
+_tx_misra_void_to_event_flags_pointer_convert:
+_tx_misra_void_to_ulong_pointer_convert:
+_tx_misra_void_to_mutex_pointer_convert:
+_tx_misra_void_to_queue_pointer_convert:
+_tx_misra_void_to_semaphore_pointer_convert:
+_tx_misra_uchar_to_void_pointer_convert:
+_tx_misra_ulong_to_thread_pointer_convert:
+_tx_misra_timer_indirect_to_void_pointer_convert:
+_tx_misra_const_char_to_char_pointer_convert:
+_tx_misra_void_to_thread_pointer_convert:
+#ifdef TX_ENABLE_EVENT_TRACE
+_tx_misra_object_to_uchar_pointer_convert:
+_tx_misra_uchar_to_object_pointer_convert:
+_tx_misra_uchar_to_header_pointer_convert:
+_tx_misra_uchar_to_entry_pointer_convert:
+_tx_misra_entry_to_uchar_pointer_convert:
+#endif
+_tx_misra_char_to_uchar_pointer_convert:
+_tx_misra_event_flags_group_not_used:
+_tx_misra_event_flags_set_notify_not_used:
+_tx_misra_queue_not_used:
+_tx_misra_queue_send_notify_not_used:
+_tx_misra_semaphore_not_used:
+_tx_misra_semaphore_put_notify_not_used:
+_tx_misra_thread_entry_exit_notify_not_used:
+_tx_misra_thread_not_used:
+
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_sub:
+ MVNS R2,#+3
+ MULS R1,R2,R1
+ ADD R0,R0,R1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ulong_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
+/** UINT size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_message_copy:
+ PUSH {R4,R5}
+ LDR R3,[R0, #+0]
+ LDR R4,[R1, #+0]
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ CMP R2,#+2
+ BCC.N ??_tx_misra_message_copy_0
+ SUBS R2,R2,#+1
+ B.N ??_tx_misra_message_copy_1
+??_tx_misra_message_copy_2:
+ LDR R5,[R3, #+0]
+ STR R5,[R4, #+0]
+ ADDS R4,R4,#+4
+ ADDS R3,R3,#+4
+ SUBS R2,R2,#+1
+??_tx_misra_message_copy_1:
+ CMP R2,#+0
+ BNE.N ??_tx_misra_message_copy_2
+??_tx_misra_message_copy_0:
+ STR R3,[R0, #+0]
+ STR R4,[R1, #+0]
+ POP {R4,R5}
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
+/** TX_TIMER_INTERNAL **ptr2); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_timer_pointer_dif:
+ SUBS R0,R0,R1
+ ASRS R0,R0,#+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
+/** **ptr1, ULONG size); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_timer_pointer_add:
+ ADD R0,R0,R1, LSL #+2
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
+/** *internal_timer, TX_TIMER **user_timer); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_user_timer_pointer_get:
+ SUBS R0,#8
+ STR R0,[R1, #+0]
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
+/** VOID **highest_stack); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_thread_stack_check:
+ PUSH {R3-R5,LR}
+ MOVS R4,R0
+ MOVS R5,R1
+ BL _tx_thread_interrupt_disable
+ CMP R4,#+0
+ BEQ.N ??_tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+0]
+ LDR.N R2,??DataTable2 // 0x54485244
+ CMP R1,R2
+ BNE.N ??_tx_misra_thread_stack_check_0
+ LDR R1,[R4, #+8]
+ LDR R2,[R5, #+0]
+ CMP R1,R2
+ BCS.N ??_tx_misra_thread_stack_check_1
+ LDR R1,[R4, #+8]
+ STR R1,[R5, #+0]
+??_tx_misra_thread_stack_check_1:
+ LDR R1,[R4, #+12]
+ LDR R1,[R1, #+0]
+ CMP R1,#-269488145
+ BNE.N ??_tx_misra_thread_stack_check_2
+ LDR R1,[R4, #+16]
+ LDR R1,[R1, #+1]
+ CMP R1,#-269488145
+ BNE.N ??_tx_misra_thread_stack_check_2
+ LDR R1,[R5, #+0]
+ LDR R2,[R4, #+12]
+ CMP R1,R2
+ BCS.N ??_tx_misra_thread_stack_check_3
+??_tx_misra_thread_stack_check_2:
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_error_handler
+ BL _tx_thread_interrupt_disable
+??_tx_misra_thread_stack_check_3:
+ LDR R1,[R5, #+0]
+ LDR R1,[R1, #-4]
+ CMP R1,#-269488145
+ BEQ.N ??_tx_misra_thread_stack_check_0
+ BL _tx_thread_interrupt_restore
+ MOVS R0,R4
+ BL _tx_thread_stack_analyze
+ BL _tx_thread_interrupt_disable
+??_tx_misra_thread_stack_check_0:
+ BL _tx_thread_interrupt_restore
+ POP {R0,R4,R5,PC} // return
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
+/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
+/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_trace_event_insert:
+ PUSH {R3-R7,LR}
+ LDR.N R4,??DataTable2_1
+ LDR R4,[R4, #+0]
+ CMP R4,#+0
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R5,??DataTable2_2
+ LDR R5,[R5, #+0]
+ LDR R6,[SP, #+28]
+ TST R5,R6
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R5,??DataTable2_3
+ LDR R5,[R5, #+0]
+ LDR.N R6,??DataTable2_4
+ LDR R6,[R6, #+0]
+ CMP R5,#+0
+ BNE.N ??_tx_misra_trace_event_insert_1
+ LDR R5,[R6, #+44]
+ LDR R7,[R6, #+60]
+ LSLS R7,R7,#+16
+ ORRS R7,R7,#0x80000000
+ ORRS R5,R7,R5
+ B.N ??_tx_misra_trace_event_insert_2
+??_tx_misra_trace_event_insert_1:
+ CMP R5,#-252645136
+ BCS.N ??_tx_misra_trace_event_insert_3
+ MOVS R5,R6
+ MOVS R6,#-1
+ B.N ??_tx_misra_trace_event_insert_2
+??_tx_misra_trace_event_insert_3:
+ MOVS R6,#-252645136
+ MOVS R5,#+0
+??_tx_misra_trace_event_insert_2:
+ STR R6,[R4, #+0]
+ STR R5,[R4, #+4]
+ STR R0,[R4, #+8]
+ LDR R0,[SP, #+32]
+ STR R0,[R4, #+12]
+ STR R1,[R4, #+16]
+ STR R2,[R4, #+20]
+ STR R3,[R4, #+24]
+ LDR R0,[SP, #+24]
+ STR R0,[R4, #+28]
+ ADDS R4,R4,#+32
+ LDR.N R0,??DataTable2_5
+ LDR R0,[R0, #+0]
+ CMP R4,R0
+ BCC.N ??_tx_misra_trace_event_insert_4
+ LDR.N R0,??DataTable2_6
+ LDR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+ LDR.N R0,??DataTable2_8
+ LDR R0,[R0, #+0]
+ CMP R0,#+0
+ BEQ.N ??_tx_misra_trace_event_insert_0
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ LDR.N R1,??DataTable2_8
+ LDR R1,[R1, #+0]
+ BLX R1
+ B.N ??_tx_misra_trace_event_insert_0
+??_tx_misra_trace_event_insert_4:
+ LDR.N R0,??DataTable2_1
+ STR R4,[R0, #+0]
+ LDR.N R0,??DataTable2_7
+ LDR R0,[R0, #+0]
+ STR R4,[R0, #+32]
+??_tx_misra_trace_event_insert_0:
+ POP {R0,R4-R7,PC} // return
+
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_1:
+ DC32 _tx_trace_buffer_current_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_2:
+ DC32 _tx_trace_event_enable_bits
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_5:
+ DC32 _tx_trace_buffer_end_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_6:
+ DC32 _tx_trace_buffer_start_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_7:
+ DC32 _tx_trace_header_ptr
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_8:
+ DC32 _tx_trace_full_notify_function
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ULONG _tx_misra_time_stamp_get(VOID); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_time_stamp_get:
+ MOVS R0,#+0
+ BX LR // return
+
+#endif
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2:
+ DC32 0x54485244
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_3:
+ DC32 _tx_thread_system_state
+
+ SECTION `.text`:CODE:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+??DataTable2_4:
+ DC32 _tx_thread_current_ptr
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_always_true(void); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_always_true:
+ MOVS R0,#+1
+ BX LR // return
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** UINT _tx_misra_status_get(UINT status); */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_status_get:
+ MOVS R0,#+0
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_ipsr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_ipsr_get:
+ MRS R0, IPSR
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_control_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_control_get:
+ MRS R0, CONTROL
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_control_set(ULONG value); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_control_set:
+ MSR CONTROL, R0
+ BX LR // return
+
+
+#ifdef __ARMVFP__
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** ULONG _tx_misra_fpccr_get(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+_tx_misra_fpccr_get:
+ LDR r0, =0xE000EF34 // Build FPCCR address
+ LDR r0, [r0] // Load FPCCR value
+ BX LR // return
+
+
+/***********************************************************************************************/
+/***********************************************************************************************/
+/** */
+/** void _tx_misra_vfp_touch(void); */
+/** */
+/***********************************************************************************************/
+/***********************************************************************************************/
+
+ SECTION `.text`:CODE:NOROOT(1)
+ THUMB
+_tx_misra_vfp_touch:
+ vmov.f32 s0, s0
+ BX LR // return
+
+#endif
+
+
+ SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2)
+ SECTION_TYPE SHT_PROGBITS, 0
+ DATA
+ DC32 0
+
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_restore.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_restore.s
new file mode 100644
index 00000000..6e4fa971
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_restore.s
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* */
+/* 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_execution_isr_exit
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is not needed for Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_exit] Execution profiling ISR exit */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ PUBLIC _tx_thread_context_restore
+_tx_thread_context_restore:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_save.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_save.s
new file mode 100644
index 00000000..d05bf887
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_context_save.s
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* */
+/* 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_execution_isr_enter
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is not needed for Cortex-M. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* [_tx_execution_isr_enter] Execution profiling ISR enter */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ PUBLIC _tx_thread_context_save
+_tx_thread_context_save:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the ISR enter function to indicate an ISR is starting. */
+ PUSH {r0, lr} // Save return address
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r0, lr} // Recover return address
+#endif
+
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_control.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_control.s
new file mode 100644
index 00000000..6f0e66a3
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_control.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ PUBLIC _tx_thread_interrupt_control
+_tx_thread_interrupt_control:
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Pickup current interrupt posture
+ MSR BASEPRI, r0 // Apply the new interrupt posture
+ MOV r0, r1 // Transfer old to return register
+#else
+ MRS r1, PRIMASK // Pickup current interrupt lockout
+ MSR PRIMASK, r0 // Apply the new interrupt lockout
+ MOV r0, r1 // Transfer old to return register
+#endif
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_disable.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_disable.s
new file mode 100644
index 00000000..d2809173
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_disable.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts and returning */
+/* the previous interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(VOID)
+// {
+ PUBLIC _tx_thread_interrupt_disable
+_tx_thread_interrupt_disable:
+ /* Return current interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r0, BASEPRI
+ LDR r1, =TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ MRS r0, PRIMASK
+ CPSID i
+#endif
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_restore.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_restore.s
new file mode 100644
index 00000000..cdc493f8
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_interrupt_restore.s
@@ -0,0 +1,75 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring the previous */
+/* interrupt lockout posture. */
+/* */
+/* INPUT */
+/* */
+/* previous_posture Previous interrupt posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_interrupt_restore(UINT previous_posture)
+// {
+ PUBLIC _tx_thread_interrupt_restore
+_tx_thread_interrupt_restore:
+ /* Restore previous interrupt lockout posture. */
+#ifdef TX_PORT_USE_BASEPRI
+ MSR BASEPRI, r0
+#else
+ MSR PRIMASK, r0
+#endif
+ BX lr
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s
new file mode 100644
index 00000000..7bcebb6c
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s
@@ -0,0 +1,383 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_execute_ptr
+ EXTERN _tx_timer_time_slice
+ EXTERN _tx_thread_system_stack_ptr
+ EXTERN _tx_thread_preempt_disable
+ EXTERN _tx_execution_thread_enter
+ EXTERN _tx_execution_thread_exit
+ EXTERN _tx_thread_secure_stack_context_restore
+ EXTERN _tx_thread_secure_stack_context_save
+ EXTERN _tx_thread_secure_mode_stack_allocate
+ EXTERN _tx_thread_secure_mode_stack_free
+ EXTERN _tx_thread_secure_mode_stack_initialize
+#ifdef TX_LOW_POWER
+ EXTERN tx_low_power_enter
+ EXTERN tx_low_power_exit
+#endif
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule Cortex-Mxx/IAR */
+/* 6.2.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 04-02-2021 Scott Larson Modified comment(s), added */
+/* low power code, */
+/* resulting in version 6.1.6 */
+/* 06-02-2021 Scott Larson Added secure stack initialize */
+/* in SVC handler, */
+/* resulting in version 6.1.7 */
+/* 04-25-2022 Scott Larson Added BASEPRI support, */
+/* resulting in version 6.1.11 */
+/* 03-08-2023 Scott Larson Added preproc FPU option, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ PUBLIC _tx_thread_schedule
+_tx_thread_schedule:
+ /* This function should only ever be called on Cortex-M
+ from the first schedule request. Subsequent scheduling occurs
+ from the PendSV handling routine below. */
+
+ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
+ MOV r0, #0 // Build value for TX_FALSE
+ LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ STR r0, [r2, #0] // Clear preempt disable flag
+
+#ifdef __ARMVFP__
+ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
+ MRS r0, CONTROL // Pickup current CONTROL register
+ BIC r0, r0, #4 // Clear the FPCA bit
+ MSR CONTROL, r0 // Setup new CONTROL register
+#endif
+
+ /* Enable interrupts */
+ CPSIE i
+
+ /* Enter the scheduler for the first time. */
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ DSB // Complete all memory accesses
+ ISB // Flush pipeline
+
+ /* Wait here for the PendSV to take place. */
+
+__tx_wait_here:
+ B __tx_wait_here // Wait for the PendSV to happen
+// }
+
+ /* Generic context switching PendSV handler. */
+
+ PUBLIC PendSV_Handler
+PendSV_Handler:
+__tx_ts_handler:
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+ PUSH {r0, lr} // Save LR (and r0 just for alignment)
+ BL _tx_execution_thread_exit // Call the thread exit function
+ POP {r0, lr} // Recover LR
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r0
+#else
+ CPSIE i // Enable interrupts
+#endif /* TX_PORT_USE_BASEPRI */
+#endif /* EXECUTION PROFILE */
+
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ MOV r3, #0 // Build NULL value
+ LDR r1, [r0] // Pickup current thread pointer
+
+ /* Determine if there is a current thread to finish preserving. */
+
+ CBZ r1, __tx_ts_new // If NULL, skip preservation
+
+ /* Recover PSP and preserve current thread context. */
+
+ STR r3, [r0] // Set _tx_thread_current_ptr to NULL
+ MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
+ STMDB r12!, {r4-r11} // Save its remaining registers
+#ifdef __ARMVFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_save
+ VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
+_skip_vfp_save:
+#endif
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ STMDB r12!, {LR} // Save LR on the stack
+ STR r12, [r1, #8] // Save the thread stack pointer
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // Save secure context
+ LDR r5, [r1,#0x90] // Load secure stack index
+ CBZ r5, _skip_secure_save // Skip save if there is no secure context
+ PUSH {r0,r1,r2,r3} // Save scratch registers
+ MOV r0, r1 // Move thread ptr to r0
+ BL _tx_thread_secure_stack_context_save // Save secure stack
+ POP {r0,r1,r2,r3} // Restore secure registers
+_skip_secure_save:
+#endif
+
+ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
+
+ LDR r5, [r4] // Pickup current time-slice
+ CBZ r5, __tx_ts_new // If not active, skip processing
+
+ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
+
+ STR r5, [r1, #24] // Save current time-slice
+
+ /* Clear the global time-slice. */
+
+ STR r3, [r4] // Clear time-slice
+
+ /* Executing thread is now completely preserved!!! */
+
+__tx_ts_new:
+
+ /* Now we are looking for a new thread to execute! */
+
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Is there another thread ready to execute?
+ CBZ r1, __tx_ts_wait // No, skip to the wait processing
+
+ /* Yes, another thread is ready for else, make the current thread the new thread. */
+
+ STR r1, [r0] // Setup the current thread pointer to the new thread
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+
+ /* Increment the thread run count. */
+
+__tx_ts_restore:
+ LDR r7, [r1, #4] // Pickup the current thread run count
+ LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
+ LDR r5, [r1, #24] // Pickup thread's current time-slice
+ ADD r7, r7, #1 // Increment the thread run count
+ STR r7, [r1, #4] // Store the new run count
+
+ /* Setup global time-slice with thread's current time-slice. */
+
+ STR r5, [r4] // Setup global time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+ /* Call the thread entry function to indicate the thread is executing. */
+ PUSH {r0, r1} // Save r0 and r1
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ POP {r0, r1} // Recover r0 and r1
+#endif
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // Restore secure context
+ LDR r0, [r1,#0x90] // Load secure stack index
+ CBZ r0, _skip_secure_restore // Skip restore if there is no secure context
+ PUSH {r0,r1} // Save r1 (and dummy r0)
+ MOV r0, r1 // Move thread ptr to r0
+ BL _tx_thread_secure_stack_context_restore // Restore secure stack
+ POP {r0,r1} // Restore r1 (and dummy r0)
+_skip_secure_restore:
+#endif
+
+ /* Restore the thread context and PSP. */
+ LDR r12, [r1, #12] // Get stack start
+ MSR PSPLIM, r12 // Set stack limit
+ LDR r12, [r1, #8] // Pickup thread's stack pointer
+ LDMIA r12!, {LR} // Pickup LR
+#ifdef __ARMVFP__
+ TST LR, #0x10 // Determine if the VFP extended frame is present
+ BNE _skip_vfp_restore // If not, skip VFP restore
+ VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
+_skip_vfp_restore:
+#endif
+ LDMIA r12!, {r4-r11} // Recover thread's registers
+ MSR PSP, r12 // Setup the thread's stack pointer
+
+ BX lr // Return to thread!
+
+ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
+ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
+ are disabled to allow use of WFI for waiting for a thread to arrive. */
+
+__tx_ts_wait:
+#ifdef TX_PORT_USE_BASEPRI
+ LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
+ MSR BASEPRI, r1
+#else
+ CPSID i // Disable interrupts
+#endif
+ LDR r1, [r2] // Pickup the next thread to execute pointer
+ STR r1, [r0] // Store it in the current pointer
+ CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_enter // Possibly enter low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_ENABLE_WFI
+ DSB // Ensure no outstanding memory transactions
+ WFI // Wait for interrupt
+ ISB // Ensure pipeline is flushed
+#endif
+
+#ifdef TX_LOW_POWER
+ PUSH {r0-r3}
+ BL tx_low_power_exit // Exit low power mode
+ POP {r0-r3}
+#endif
+
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_wait // Loop to continue waiting
+
+ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
+ already in the handler! */
+__tx_ts_ready:
+ MOV r7, #0x08000000 // Build clear PendSV value
+ MOV r8, #0xE000E000 // Build base NVIC address
+ STR r7, [r8, #0xD04] // Clear any PendSV
+
+ /* Re-enable interrupts and restore new thread. */
+#ifdef TX_PORT_USE_BASEPRI
+ MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
+ MSR BASEPRI, r4
+#else
+ CPSIE i // Enable interrupts
+#endif
+ B __tx_ts_restore // Restore the thread
+// }
+
+
+#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE))
+ // SVC_Handler is not needed when ThreadX is running in single mode.
+ PUBLIC SVC_Handler
+SVC_Handler:
+ TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2
+ ITE EQ
+ MRSEQ r0, MSP // Get MSP if return stack is MSP
+ MRSNE r0, PSP // Get PSP if return stack is PSP
+
+ LDR r1, [r0,#24] // Load saved PC from stack
+ LDRB r1, [r1,#-2] // Load SVC number
+
+ CMP r1, #1 // Is it a secure stack allocate request?
+ BEQ _tx_svc_secure_alloc // Yes, go there
+
+ CMP r1, #2 // Is it a secure stack free request?
+ BEQ _tx_svc_secure_free // Yes, go there
+
+ CMP r1, #3 // Is it a secure stack init request?
+ BEQ _tx_svc_secure_init // Yes, go there
+
+ // Unknown SVC argument - just return
+ BX lr
+
+_tx_svc_secure_alloc:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ LDM r0, {r0-r3} // Load function parameters from stack
+ BL _tx_thread_secure_mode_stack_allocate
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ STR r0,[r12] // Store function return value
+ BX lr
+_tx_svc_secure_free:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ LDM r0, {r0-r3} // Load function parameters from stack
+ BL _tx_thread_secure_mode_stack_free
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ STR r0,[r12] // Store function return value
+ BX lr
+_tx_svc_secure_init:
+ PUSH {r0,lr} // Save SP and EXC_RETURN
+ BL _tx_thread_secure_mode_stack_initialize
+ POP {r12,lr} // Restore SP and EXC_RETURN
+ BX lr
+#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE
+
+
+ PUBLIC _tx_vfp_access
+_tx_vfp_access:
+#ifdef __ARMVFP__
+ VMOV.F32 s0, s0 // Simply access the VFP
+#endif
+ BX lr // Return to caller
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack.c b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack.c
new file mode 100644
index 00000000..2a2548ff
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack.c
@@ -0,0 +1,597 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "tx_api.h"
+
+/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined,
+ no secure stack functionality is needed. */
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+
+#define TX_SOURCE_CODE
+
+#include <cmsis_compiler.h> /* For intrinsic functions. */
+#include "tx_secure_interface.h" /* Interface for NS code. */
+
+/* Minimum size of secure stack. */
+#ifndef TX_THREAD_SECURE_STACK_MINIMUM
+#define TX_THREAD_SECURE_STACK_MINIMUM 256
+#endif
+/* Maximum size of secure stack. */
+#ifndef TX_THREAD_SECURE_STACK_MAXIMUM
+#define TX_THREAD_SECURE_STACK_MAXIMUM 1024
+#endif
+
+/* 8 bytes added to stack size to "seal" stack. */
+#define TX_THREAD_STACK_SEAL_SIZE 8
+#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5
+
+/* max number of Secure context */
+#ifndef TX_MAX_SECURE_CONTEXTS
+#define TX_MAX_SECURE_CONTEXTS 32
+#endif
+#define TX_INVALID_SECURE_CONTEXT_IDX (-1)
+
+/* Secure stack info struct to hold stack start, stack limit,
+ current stack pointer, and pointer to owning thread.
+ This will be allocated for each thread with a secure stack. */
+typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
+{
+ VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */
+ VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */
+ VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */
+ TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */
+ INT tx_next_free_index; /* Next free index of free secure context */
+} TX_THREAD_SECURE_STACK_INFO;
+
+/* Static secure contexts */
+static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS];
+/* Head of free secure context */
+static INT tx_head_free_index = 0U;
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_initialize Cortex-Mxx/IAR */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function initializes secure mode to use PSP stack. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* status */
+/* */
+/* 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 */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 06-02-2021 Scott Larson Change name, execute in */
+/* handler mode, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_initialize(void)
+{
+UINT status;
+INT index;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ if (__get_IPSR() == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+ else
+ {
+ /* Set secure mode to use PSP. */
+ __set_CONTROL(__get_CONTROL() | 2);
+
+ /* 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);
+
+ for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++)
+ {
+
+ /* Check last index and mark next free to invalid index */
+ if(index == (TX_MAX_SECURE_CONTEXTS - 1))
+ {
+ tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+ else
+ {
+ tx_thread_secure_context[index].tx_next_free_index = index + 1;
+ }
+ }
+
+ status = TX_SUCCESS;
+ }
+ return status;
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_allocate Cortex-Mxx/IAR */
+/* 6.1.11a */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allocates a thread's secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of stack to allocates */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_SIZE_ERROR Invalid stack size */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* __get_IPSR Intrinsic to get IPSR */
+/* malloc Compiler's malloc 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 */
+/* */
+/* SVC Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* added stack sealing, */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* 05-02-2022 Scott Larson Modified comment(s), added */
+/* TX_INTERRUPT_SAVE_AREA, */
+/* resulting in version 6.1.11a*/
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+UCHAR *stack_mem;
+INT secure_context_index;
+
+ status = TX_SUCCESS;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ if (__get_IPSR() == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+ else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM)
+ {
+ status = TX_SIZE_ERROR;
+ }
+
+ /* Check if thread already has secure stack allocated. */
+ else if (thread_ptr -> tx_thread_secure_stack_context != 0)
+ {
+ status = TX_THREAD_ERROR;
+ }
+
+ else
+ {
+ TX_DISABLE
+
+ /* Allocate free index for secure stack info. */
+ if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX)
+ {
+ secure_context_index = tx_head_free_index;
+ tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index;
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+ else
+ {
+ secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX;
+ }
+
+ TX_RESTORE
+
+ if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX)
+ {
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* If stack info allocated, allocate a stack & seal. */
+ stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE);
+
+ if(stack_mem != TX_NULL)
+ {
+ /* Secure stack has been allocated, save in the stack info struct. */
+ info_ptr -> tx_thread_secure_stack_limit = stack_mem;
+ info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size;
+ info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start;
+ info_ptr -> tx_thread_ptr = thread_ptr;
+
+ /* Seal bottom of stack. */
+ *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE;
+
+ /* Save secure context id (i.e non-zero base index) in thread. */
+ thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1);
+
+ /* Check if this thread is running by looking at its stack start and PSPLIM_NS */
+ if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == __TZ_get_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));
+ }
+ }
+
+ else
+ {
+ TX_DISABLE
+
+ /* Stack not allocated, free the info struct. */
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
+ tx_head_free_index = secure_context_index;
+ TX_RESTORE
+
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ else
+ {
+ status = TX_NO_MEMORY;
+ }
+ }
+
+ return(status);
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_mode_stack_free Cortex-Mxx/IAR */
+/* 6.1.11a */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function frees a thread's secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* __get_IPSR Intrinsic to get IPSR */
+/* free Compiler's free() function */
+/* */
+/* CALLED BY */
+/* */
+/* SVC Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* 05-02-2022 Scott Larson Modified comment(s), added */
+/* TX_INTERRUPT_SAVE_AREA, */
+/* resulting in version 6.1.11a*/
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr)
+{
+TX_INTERRUPT_SAVE_AREA
+UINT status;
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+INT secure_context_index;
+
+ status = TX_SUCCESS;
+
+ /* Pickup stack info id from thread. */
+ secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* Make sure function is called from interrupt (threads should not call). */
+ if (__get_IPSR() == 0)
+ {
+ status = TX_CALLER_ERROR;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ status = TX_THREAD_ERROR;
+ }
+ else
+ {
+
+ /* Pickup stack info from static array of secure contexts. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ status = TX_THREAD_ERROR;
+ }
+
+ else
+ {
+
+ /* Free secure stack. */
+ free(info_ptr -> tx_thread_secure_stack_limit);
+
+ TX_DISABLE
+
+ /* Free info struct. */
+ tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
+ tx_head_free_index = secure_context_index;
+ TX_RESTORE
+
+ /* Clear secure context from thread. */
+ thread_ptr -> tx_thread_secure_stack_context = 0;
+ }
+ }
+
+ return(status);
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_context_save Cortex-Mxx/IAR */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves context of the secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* 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 */
+/* */
+/* CALLED BY */
+/* */
+/* PendSV Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 06-02-2021 Scott Larson Fix stack pointer save, */
+/* resulting in version 6.1.7 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr)
+{
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+ULONG sp;
+INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* This function should be called from scheduler only. */
+ if (__get_IPSR() == 0)
+ {
+ return;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ return;
+ }
+
+ /* Pickup the secure context pointer. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ return;
+ }
+
+ /* Check that stack pointer is in range */
+ sp = __get_PSP();
+ if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) ||
+ (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start))
+ {
+ return;
+ }
+
+ /* Save stack pointer. */
+ info_ptr -> tx_thread_secure_stack_ptr = (VOID *) 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);
+
+ return;
+}
+
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_context_restore Cortex-Mxx/IAR */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function restores context of the secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* __get_IPSR Intrinsic to get IPSR */
+/* __set_PSPLIM Intrinsic to set PSP limit */
+/* __set_PSP Intrinsic to set PSP */
+/* */
+/* CALLED BY */
+/* */
+/* PendSV Handler */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 10-16-2020 Scott Larson Modified comment(s), */
+/* resulting in version 6.1.1 */
+/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
+/* secure stack allocation, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+__attribute__((cmse_nonsecure_entry))
+void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr)
+{
+TX_THREAD_SECURE_STACK_INFO *info_ptr;
+INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
+
+ /* This function should be called from scheduler only. */
+ if (__get_IPSR() == 0)
+ {
+ return;
+ }
+
+ /* Check if secure context index is in valid range. */
+ else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
+ {
+ return;
+ }
+
+ /* Pickup the secure context pointer. */
+ info_ptr = &tx_thread_secure_context[secure_context_index];
+
+ /* Check that this secure context is for this thread. */
+ if (info_ptr -> tx_thread_ptr != thread_ptr)
+ {
+ return;
+ }
+
+ /* 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);
+
+ return;
+}
+
+#endif
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_allocate.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_allocate.s
new file mode 100644
index 00000000..5f86bb2e
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_allocate.s
@@ -0,0 +1,80 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_allocate Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to allocate a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of secure stack to */
+/* allocate */
+/* */
+/* OUTPUT */
+/* */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* SVC 1 */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+// {
+ EXPORT _tx_thread_secure_stack_allocate
+_tx_thread_secure_stack_allocate:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ MRS r3, PRIMASK // Save interrupt mask
+ CPSIE i // Enable interrupts for SVC call
+ SVC 1
+ CMP r3, #0 // If interrupts enabled, just return
+ BEQ _alloc_return_interrupt_enabled
+ CPSID i // Otherwise, disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+_alloc_return_interrupt_enabled
+ BX lr
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_free.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_free.s
new file mode 100644
index 00000000..9394b62b
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_free.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_free Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to free a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* SVC 2 */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr)
+// {
+ EXPORT _tx_thread_secure_stack_free
+_tx_thread_secure_stack_free:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ MRS r3, PRIMASK // Save interrupt mask
+ CPSIE i // Enable interrupts for SVC call
+ SVC 2
+ CMP r3, #0 // If interrupts enabled, just return
+ BEQ _free_return_interrupt_enabled
+ CPSID i // Otherwise, disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+_free_return_interrupt_enabled
+ BX lr
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_initialize.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_initialize.s
new file mode 100644
index 00000000..1c19fb50
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_secure_stack_initialize.s
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_initialize Cortex-Mxx/IAR */
+/* 6.1.12 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enters the SVC handler to initialize a secure stack. */
+/* */
+/* INPUT */
+/* */
+/* none */
+/* */
+/* OUTPUT */
+/* */
+/* none */
+/* */
+/* CALLS */
+/* */
+/* SVC 3 */
+/* */
+/* CALLED BY */
+/* */
+/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
+/* 07-29-2022 Scott Larson Modified comments and changed */
+/* secure stack initialization */
+/* macro to port-specific, */
+/* resulting in version 6.1.12 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_secure_stack_initialize(VOID)
+// {
+ EXPORT _tx_thread_secure_stack_initialize
+_tx_thread_secure_stack_initialize:
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+ CPSIE i // Enable interrupts for SVC call
+ SVC 3
+ CPSID i // Disable interrupts
+#else
+ MOV r0, #0xFF // Feature not enabled
+#endif
+ BX lr
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_stack_build.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_stack_build.s
new file mode 100644
index 00000000..466afe15
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_stack_build.s
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build Cortex-Mxx/IAR */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ PUBLIC _tx_thread_stack_build
+_tx_thread_stack_build:
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-M should look like the following after it is built:
+
+ Stack Top:
+ LR Interrupted LR (LR at time of PENDSV)
+ r4 Initial value for r4
+ r5 Initial value for r5
+ r6 Initial value for r6
+ r7 Initial value for r7
+ r8 Initial value for r8
+ r9 Initial value for r9
+ r10 Initial value for r10
+ r11 Initial value for r11
+ r0 Initial value for r0 (Hardware stack starts here!!)
+ r1 Initial value for r1
+ r2 Initial value for r2
+ r3 Initial value for r3
+ r12 Initial value for r12
+ lr Initial value for lr
+ pc Initial value for pc
+ xPSR Initial value for xPSR
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #0x7 // Align frame for 8-byte alignment
+ SUB r2, r2, #68 // Subtract frame size
+#ifdef TX_SINGLE_MODE_SECURE
+ LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode
+#else
+ LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP
+#endif
+ STR r3, [r2, #0] // Save on the stack
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #4] // Store initial r4
+ STR r3, [r2, #8] // Store initial r5
+ STR r3, [r2, #12] // Store initial r6
+ STR r3, [r2, #16] // Store initial r7
+ STR r3, [r2, #20] // Store initial r8
+ STR r3, [r2, #24] // Store initial r9
+ STR r3, [r2, #28] // Store initial r10
+ STR r3, [r2, #32] // Store initial r11
+
+ /* Hardware stack follows. */
+
+ STR r3, [r2, #36] // Store initial r0
+ STR r3, [r2, #40] // Store initial r1
+ STR r3, [r2, #44] // Store initial r2
+ STR r3, [r2, #48] // Store initial r3
+ STR r3, [r2, #52] // Store initial r12
+ MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
+ STR r3, [r2, #56] // Store initial lr
+ STR r1, [r2, #60] // Store initial pc
+ MOV r3, #0x01000000 // Only T-bit need be set
+ STR r3, [r2, #64] // Store initial xPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s
new file mode 100644
index 00000000..0506de15
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/* */
+/* 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:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX 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 */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ PUBLIC _tx_thread_system_return
+_tx_thread_system_return:
+ /* Return to real scheduler via PendSV. Note that this routine is often
+ replaced with in-line assembly in tx_port.h to improved performance. */
+
+ MOV r0, #0x10000000 // Load PENDSVSET bit
+ MOV r1, #0xE000E000 // Load NVIC base
+ STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
+ MRS r0, IPSR // Pickup IPSR
+ CMP r0, #0 // Is it a thread returning?
+ BNE _isr_context // If ISR, skip interrupt enable
+#ifdef TX_PORT_USE_BASEPRI
+ MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
+ MOV r0, #0
+ MSR BASEPRI, r0 // Enable interrupts
+ MSR BASEPRI, r1 // Restore original interrupt posture
+#else
+ MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
+ CPSIE i // Enable interrupts
+ MSR PRIMASK, r1 // Restore original interrupt posture
+#endif
+_isr_context:
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_timer_interrupt.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_timer_interrupt.s
new file mode 100644
index 00000000..e206eba3
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ EXTERN _tx_timer_time_slice
+ EXTERN _tx_timer_system_clock
+ EXTERN _tx_timer_current_ptr
+ EXTERN _tx_timer_list_start
+ EXTERN _tx_timer_list_end
+ EXTERN _tx_timer_expired_time_slice
+ EXTERN _tx_timer_expired
+ EXTERN _tx_thread_time_slice
+ EXTERN _tx_timer_expiration_process
+ EXTERN _tx_thread_current_ptr
+ EXTERN _tx_thread_execute_ptr
+ EXTERN _tx_thread_preempt_disable
+
+ SECTION `.text`:CODE:NOROOT(2)
+ THUMB
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt Cortex-Mxx/IAR */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* expiration functions are called. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+ PUBLIC _tx_timer_interrupt
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CBZ r2, __tx_timer_no_time_slice // Is it non-active?
+ // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+
+ SUB r2, r2, #1 // Decrement the time-slice
+ STR r2, [r3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ // if (__tx_timer_time_slice == 0)
+
+ CBNZ r2, __tx_timer_no_time_slice // Has it expired?
+ // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV r0, #1 // Build expired value
+ STR r0, [r3, #0] // Set time-slice expiration flag
+
+ // }
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CBZ r2, __tx_timer_no_timer // Is there anything in the list?
+ // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR r2, [r3, #0] // Pickup time-slice expired flag
+ CBNZ r2, __tx_something_expired // Did a time-slice expire?
+ // If non-zero, time-slice expired
+ LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
+ // No, nothing expired
+
+__tx_something_expired:
+
+ PUSH {r0, lr} // Save the lr register on the stack
+ // and save r0 just to keep 8-byte alignment
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CBZ r0, __tx_timer_dont_activate // Check for timer expiration
+ // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR r2, [r3, #0] // Pickup the actual flag
+ CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
+ // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+ LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r1, [r0] // Is the preempt disable flag set?
+ CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ LDR r1, [r0] // Pickup the current thread pointer
+ LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
+ LDR r3, [r2] // Pickup the execute thread pointer
+ LDR r0, =0xE000ED04 // Build address of control register
+ LDR r2, =0x10000000 // Build value for PendSV bit
+ CMP r1, r3 // Are they the same?
+ BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
+ STR r2, [r0] // Not the same, issue the PendSV for preemption
+__tx_timer_skip_time_slice:
+ // }
+
+__tx_timer_not_ts_expiration:
+
+ POP {r0, lr} // Recover lr register (r0 is just there for
+ // the 8-byte stack alignment
+
+ // }
+
+__tx_timer_nothing_expired:
+
+ DSB // Complete all memory access
+ BX lr // Return to caller
+// }
+ END
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_allocate.c b/ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_allocate.c
new file mode 100644
index 00000000..caa47139
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_allocate.c
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_secure_stack_allocate Cortex-Mxx */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the secure stack allocate */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* stack_size Size of secure stack to */
+/* allocate */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_secure_stack_allocate Actual stack alloc function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
+{
+#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE)
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+UINT status;
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+ /* Is call from an interrupt and not initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+ /* Call actual secure stack allocate function. */
+ status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size);
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
diff --git a/ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_free.c b/ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_free.c
new file mode 100644
index 00000000..0e1efcf4
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/iar/src/txe_thread_secure_stack_free.c
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* */
+/* 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_initialize.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txe_thread_secure_stack_free Cortex-Mxx */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the secure stack free */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Thread control block pointer */
+/* */
+/* OUTPUT */
+/* */
+/* TX_THREAD_ERROR Invalid thread pointer */
+/* TX_CALLER_ERROR Invalid caller of function */
+/* status Actual completion status */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_secure_stack_free Actual stack free function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr)
+{
+#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE)
+ return(TX_FEATURE_NOT_ENABLED);
+#else
+UINT status;
+
+ /* Default status to success. */
+ status = TX_SUCCESS;
+
+ /* Check for an invalid thread pointer. */
+ if (thread_ptr == TX_NULL)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Now check for invalid thread ID. */
+ else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
+ {
+
+ /* Thread pointer is invalid, return appropriate error code. */
+ status = TX_THREAD_ERROR;
+ }
+
+ /* Check for interrupt call. */
+ if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+ {
+ /* Is call from an interrupt and not initialization? */
+ if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+ {
+ /* Invalid caller of this function, return appropriate error code. */
+ status = TX_CALLER_ERROR;
+ }
+ }
+
+ /* Determine if everything is okay. */
+ if (status == TX_SUCCESS)
+ {
+
+ /* Call actual secure stack allocate function. */
+ status = _tx_thread_secure_stack_free(thread_ptr);
+ }
+
+ /* Return completion status. */
+ return(status);
+#endif
+}
diff --git a/ports_arch/ARMv8-M/threadx/inc/tx_port.h b/ports_arch/ARMv8-M/threadx/inc/tx_port.h
new file mode 100644
index 00000000..0092254c
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/inc/tx_port.h
@@ -0,0 +1,658 @@
+/**************************************************************************/
+/* */
+/* 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 Cortex-Mxx */
+/* 6.2.1 */
+/* */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* This file replaces the previous Cortex-Mxx files. It unifies */
+/* the Cortex-Mxx compilers into one common file. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 03-02-2021 Scott Larson Modified comment(s), added */
+/* ULONG64_DEFINED, */
+/* resulting in version 6.1.5 */
+/* 06-02-2021 Scott Larson Modified comment(s), removed */
+/* unneeded header file, funcs */
+/* set_control and get_control */
+/* changed to inline, */
+/* added symbol to enable */
+/* stack error handler, */
+/* resulting in version 6.1.7 */
+/* 10-15-2021 Scott Larson Modified comment(s), improved */
+/* stack check error handling, */
+/* resulting in version 6.1.9 */
+/* 01-31-2022 Scott Larson Modified comment(s), unified */
+/* this file across compilers, */
+/* fixed predefined macro, */
+/* resulting in version 6.1.10 */
+/* 04-25-2022 Scott Larson Modified comments and added */
+/* volatile to registers, */
+/* resulting in version 6.1.11 */
+/* 07-29-2022 Scott Larson Modified comments and changed */
+/* secure stack initialization */
+/* macro to port-specific, */
+/* described BASEPRI usage, */
+/* resulting in version 6.1.12 */
+/* 03-08-2023 Scott Larson Removed unneeded #include, */
+/* resulting in version 6.2.1 */
+/* */
+/**************************************************************************/
+
+#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 /* TX_INCLUDE_USER_DEFINE_FILE */
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __ICCARM__
+#include <intrinsics.h> /* IAR Intrinsics */
+#define __asm__ __asm /* Define to make all inline asm from each compiler look similar */
+#define _tx_control_get __get_CONTROL
+#define _tx_control_set __set_CONTROL
+#define _tx_ipsr_get __get_IPSR
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+#include <yvals.h>
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+#endif /* __ICCARM__ */
+
+
+/* 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 unsigned long long ULONG64;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#define ULONG64_DEFINED
+
+/* Function prototypes for this port. */
+struct TX_THREAD_STRUCT;
+UINT _txe_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *thread_ptr, ULONG stack_size);
+UINT _txe_thread_secure_stack_free(struct TX_THREAD_STRUCT *thread_ptr);
+UINT _tx_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *tx_thread, ULONG stack_size);
+UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
+
+/* Define the system API mappings based on the error checking
+ selected by the user. Note: this section is only applicable to
+ application source code, hence the conditional that turns off this
+ stuff when the include file is processed by the ThreadX source. */
+
+#ifndef TX_SOURCE_CODE
+
+
+/* Determine if error checking is desired. If so, map API functions
+ to the appropriate error checking front-ends. Otherwise, map API
+ functions to the core functions that actually perform the work.
+ Note: error checking is enabled by default. */
+
+#ifdef TX_DISABLE_ERROR_CHECKING
+
+/* Services without error checking. */
+
+#define tx_thread_secure_stack_allocate _tx_thread_secure_stack_allocate
+#define tx_thread_secure_stack_free _tx_thread_secure_stack_free
+
+#else
+
+/* Services with error checking. */
+
+#define tx_thread_secure_stack_allocate _txe_thread_secure_stack_allocate
+#define tx_thread_secure_stack_free _txe_thread_secure_stack_free
+
+#endif /* TX_DISABLE_ERROR_CHECKING */
+#endif /* TX_SOURCE_CODE */
+
+/* This port has a usage fault handler in _tx_initialize_low_level for stack exceptions. */
+#define TX_PORT_THREAD_STACK_ERROR_HANDLING
+
+/* 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 200 /* 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
+
+/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts.
+If using BASEPRI is desired, define the following two symbols for both c and assembly files:
+TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK.
+TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask.
+Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run.
+*/
+
+/* Define various constants for the ThreadX Cortex-M port. */
+
+#define TX_INT_DISABLE 1 /* Disable interrupts */
+#define TX_INT_ENABLE 0 /* Enable interrupts */
+
+
+/* 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 *((volatile ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
+#endif
+#else
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#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. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* 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. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#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
+
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+/* IAR library support */
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+/* ThreadX in non-secure zone with calls to secure zone. */
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; \
+ VOID *tx_thread_iar_tls_pointer;
+#else
+/* ThreadX in only one zone. */
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
+#endif
+
+#else
+/* No IAR library support */
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+/* ThreadX in non-secure zone with calls to secure zone. */
+#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context;
+#else
+/* ThreadX in only one zone. */
+#define TX_THREAD_EXTENSION_2
+#endif
+
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#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. */
+#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
+void *_tx_iar_create_per_thread_tls_area(void);
+void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
+void __iar_Initlocks(void);
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
+
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); \
+ if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);}
+#else
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
+ thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
+#endif
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
+
+#else /* No IAR library support. */
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);}
+#else
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#endif
+#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
+
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+/* Define the size of the secure stack for the timer thread and use the extension to allocate the secure stack. */
+#define TX_TIMER_THREAD_SECURE_STACK_SIZE 256
+#define TX_TIMER_INITIALIZE_EXTENSION(status) _tx_thread_secure_stack_allocate(&_tx_timer_thread, TX_TIMER_THREAD_SECURE_STACK_SIZE);
+#endif
+
+
+#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
+
+#ifdef TX_MISRA_ENABLE
+
+ULONG _tx_misra_control_get(void);
+void _tx_misra_control_set(ULONG value);
+ULONG _tx_misra_fpccr_get(void);
+void _tx_misra_vfp_touch(void);
+
+#else /* TX_MISRA_ENABLE not defined */
+
+#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
+
+__attribute__( ( always_inline ) ) static inline ULONG _tx_control_get(void)
+{
+ULONG control_value;
+
+ __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
+ return(control_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG control_value)
+{
+ __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
+}
+
+#endif /* __GNUC__ */
+
+/* Touch VFP register in order to flush. Works for AC6/GCC/IAR compilers. */
+#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
+
+#endif /* TX_MISRA_ENABLE */
+
+/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
+ in order to ensure no lazy stacking will occur. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_control_set(_tx_vfp_state); \
+ }
+#else
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ }
+#endif
+
+/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
+ If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
+ this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
+ the lazy FPU save, then restore the CONTROL.FPCA state. */
+
+#ifndef TX_MISRA_ENABLE
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_control_set(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ TX_VFP_TOUCH(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = _tx_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_control_set(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#else
+
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
+ ULONG _tx_system_state; \
+ _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
+ if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ else \
+ { \
+ ULONG _tx_fpccr; \
+ _tx_fpccr = _tx_misra_fpccr_get(); \
+ _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
+ if (_tx_fpccr == ((ULONG) 0x01)) \
+ { \
+ ULONG _tx_vfp_state; \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
+ _tx_misra_vfp_touch(); \
+ if (_tx_vfp_state == ((ULONG) 0)) \
+ { \
+ _tx_vfp_state = _tx_misra_control_get(); \
+ _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
+ _tx_misra_control_set(_tx_vfp_state); \
+ } \
+ } \
+ } \
+ }
+#endif
+
+#else /* No VFP in use */
+
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
+
+
+/* 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 the get system state macro. */
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+#ifndef TX_MISRA_ENABLE
+
+#if defined(__GNUC__) /* GCC and AC6 */
+__attribute__( ( always_inline ) ) static inline UINT _tx_ipsr_get(void)
+{
+UINT ipsr_value;
+ __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
+ return(ipsr_value);
+}
+#endif /* GCC and AC6 IPSR_get function. */
+
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_ipsr_get())
+
+#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
+ULONG _tx_misra_ipsr_get(VOID);
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
+#endif /* TX_MISRA_ENABLE */
+#endif /* TX_THREAD_GET_SYSTEM_STATE */
+
+
+/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
+ indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
+ for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
+ zero after initialization for Cortex-M ports. */
+
+#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
+#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
+#endif
+
+#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
+/* Initialize secure stacks for threads calling secure functions. */
+extern void _tx_thread_secure_stack_initialize(void);
+#define TX_PORT_SPECIFIC_PRE_INITIALIZATION _tx_thread_secure_stack_initialize();
+#endif
+
+/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
+ prevent early scheduling on Cortex-M parts. */
+
+#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
+
+
+
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
+#ifdef __ICCARM__ /* IAR Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
+#elif defined(__GNUC__) /* GCC and AC6 Compiler */
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
+ __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
+#else
+#error "Compiler not supported."
+#endif
+
+
+
+/* Define the interrupt disable/restore macros. */
+
+__attribute__( ( always_inline ) ) static inline UINT __get_interrupt_posture(void)
+{
+UINT posture;
+#ifdef TX_PORT_USE_BASEPRI
+ __asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
+#else
+ __asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
+#endif
+ return(posture);
+}
+
+#ifdef TX_PORT_USE_BASEPRI
+__attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value)
+{
+ __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
+}
+#else
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
+{
+ __asm__ volatile ("CPSIE i": : : "memory");
+}
+#endif
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT int_posture)
+{
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(int_posture);
+#else
+ __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
+#endif
+}
+
+__attribute__( ( always_inline ) ) static inline UINT __disable_interrupts(void)
+{
+UINT int_posture;
+
+ int_posture = __get_interrupt_posture();
+
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(TX_PORT_BASEPRI);
+#else
+ __asm__ volatile ("CPSID i" : : : "memory");
+#endif
+ return(int_posture);
+}
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+UINT interrupt_save;
+
+ /* Set PendSV to invoke ThreadX scheduler. */
+ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
+ if (_tx_ipsr_get() == 0)
+ {
+ interrupt_save = __get_interrupt_posture();
+#ifdef TX_PORT_USE_BASEPRI
+ __set_basepri_value(0);
+#else
+ __enable_interrupts();
+#endif
+ __restore_interrupt(interrupt_save);
+ }
+}
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupt(interrupt_save);
+
+/* Redefine _tx_thread_system_return for improved performance. */
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+#else /* TX_DISABLE_INLINE is defined */
+
+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);
+#endif /* TX_DISABLE_INLINE */
+
+/* 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 Cortex-Mxx Version 6.2.1 *";
+#else
+#ifdef TX_MISRA_ENABLE
+extern CHAR _tx_version_id[100];
+#else
+extern CHAR _tx_version_id[];
+#endif
+#endif
+
+#endif
diff --git a/ports_arch/ARMv8-M/threadx/inc/tx_secure_interface.h b/ports_arch/ARMv8-M/threadx/inc/tx_secure_interface.h
new file mode 100644
index 00000000..d6fba106
--- /dev/null
+++ b/ports_arch/ARMv8-M/threadx/inc/tx_secure_interface.h
@@ -0,0 +1,61 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* tx_secure_interface.h PORTABLE C */
+/* 6.1 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the ThreadX secure thread stack components, */
+/* including data types and external references. */
+/* It is assumed that tx_api.h and tx_port.h have already been */
+/* included. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_SECURE_INTERFACE_H
+#define TX_SECURE_INTERFACE_H
+
+/* Define internal secure thread stack function prototypes. */
+
+extern UINT _tx_thread_secure_mode_stack_initialize(void);
+extern UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size);
+extern UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr);
+extern void _tx_thread_secure_stack_initialize(void);
+extern void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr);
+extern void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr);
+
+#endif
diff --git a/scripts/copy_armv7_m.sh b/scripts/copy_armv7_m.sh
new file mode 100755
index 00000000..825979a2
--- /dev/null
+++ b/scripts/copy_armv7_m.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+# There is only one tx_port.h file that covers three architectures: M3/M4/M7 and four tools: ac5/ac6/gnu/iar.
+# This file is in threadx/ports/armv7-m/inc. We are going to ignore GHS for now, but I’d like to get GHS unified as well.
+
+set -e
+
+ports_folder="ports"
+source_folder="ports_arch/ARMv7-M/threadx"
+target_mcu="cortex_m3 cortex_m4 cortex_m7"
+source_inc_folder="$source_folder/inc"
+target_inc_mcu=$target_mcu
+target_inc_ide="ac5 ac6 gnu iar keil"
+target_inc_folder="inc"
+source_src_ide="ac5 ac6 gnu iar"
+target_src_mcu=$target_mcu
+src_folder="src"
+readme="readme_threadx.txt"
+source_string="Cortex-Mx"
+target_string_pre="Cortex-M"
+
+cd $(dirname `realpath $0`)/..
+
+# Copy port files
+for mcu in $target_mcu;
+do
+ for ide in $target_inc_ide;
+ do
+ # Copy files
+ target=$ports_folder/$mcu/$ide/$target_inc_folder
+ [ -d "$target" ] || continue
+ echo "$source_inc_folder -> $target"
+ rm -rf $target
+ cp -rf $source_inc_folder $target
+
+ # String replacement
+ mcu_string="$target_string_pre${mcu: -1}"
+ if [ "$ide" == "keil" ];
+ then
+ ide_string="Keil"
+ mcu_ide_string="$mcu_string\/$ide_string"
+ else
+ ide_string="${ide^^}"
+ mcu_ide_string="$mcu_string\/$ide_string "
+ fi
+ sed -i "s/ $source_string /$mcu_ide_string/g" $target/*
+ sed -i "s/ThreadX $source_string /ThreadX $mcu_string\/$ide_string /g" $target/*
+ sed -i "s/$source_string/$mcu_string/g" $target/*
+ done
+done
+echo ""
+
+# Copy source files
+for ide in $source_src_ide;
+do
+ for mcu in $target_src_mcu;
+ do
+ # Copy source files
+ src=$source_folder/$ide/$src_folder
+ target=$ports_folder/$mcu/$ide/$src_folder
+ #[ -d "$target" ] || continue
+ echo "$src -> $target"
+ rm -rf $target
+ cp -rf $src $target
+
+ # String replacement
+ sed -i "s/$source_string/$target_string_pre${mcu: -1}/g" $target/*
+
+ # Copy readme files
+ src=$source_folder/$ide/$readme
+ target=$ports_folder/$mcu/$ide/$readme
+ #[ -f "$target" ] || continue
+ echo "$src -> $target"
+ rm -f $target
+ cp -f $src $target
+
+ # String replacement
+ sed -i "s/$source_string/$target_string_pre${mcu: -1}/g" $target
+ done
+done \ No newline at end of file
diff --git a/scripts/copy_armv8_m.sh b/scripts/copy_armv8_m.sh
new file mode 100755
index 00000000..0963ecbe
--- /dev/null
+++ b/scripts/copy_armv8_m.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+# There are two files tx_port.h and tx_secure_interface.h that cover three architectures: M33/M55/M85 and three tools: ac6/gnu/iar.
+# These files are in threadx/ports/armv8-m/inc.
+
+set -e
+
+ports_folder="ports"
+source_folder="ports_arch/ARMv8-M/threadx"
+target_mcu="cortex_m33 cortex_m55 cortex_m85"
+source_inc_folder="$source_folder/inc"
+target_inc_mcu=$target_mcu
+target_inc_ide="ac6 gnu iar"
+target_inc_folder="inc"
+source_src_ide="ac6 gnu iar"
+target_src_mcu=$target_mcu
+src_folder="src"
+readme="readme_threadx.txt"
+cmake="CMakeLists.txt"
+source_string="Cortex-Mxx"
+target_string_pre="Cortex-M"
+
+cd $(dirname `realpath $0`)/..
+
+# Copy port files
+for mcu in $target_mcu;
+do
+ for ide in $target_inc_ide;
+ do
+ # Copy files
+ target=$ports_folder/$mcu/$ide/$target_inc_folder
+ [ -d "$target" ] || mkdir -p $target
+ echo "$source_inc_folder -> $target"
+ rm -rf $target
+ cp -rf $source_inc_folder $target
+
+ # String replacement
+ mcu_string="$target_string_pre${mcu: -2}"
+ if [ "$ide" == "keil" ];
+ then
+ ide_string="Keil"
+ mcu_ide_string="$mcu_string\/$ide_string"
+ else
+ ide_string="${ide^^}"
+ mcu_ide_string="$mcu_string\/$ide_string "
+ fi
+ sed -i "s/ $source_string /$mcu_ide_string/g" $target/*
+ sed -i "s/ThreadX $source_string /ThreadX $mcu_string\/$ide_string /g" $target/*
+ sed -i "s/$source_string/$mcu_string/g" $target/*
+ done
+done
+echo ""
+
+# Copy source files
+for ide in $source_src_ide;
+do
+ for mcu in $target_src_mcu;
+ do
+ # Copy source files
+ src=$source_folder/$ide/$src_folder
+ target=$ports_folder/$mcu/$ide/$src_folder
+ #[ -d "$target" ] || continue
+ echo "$src -> $target"
+ rm -rf $target
+ cp -rf $src $target
+
+ # String replacement
+ sed -i "s/$source_string/$target_string_pre${mcu: -2}/g" $target/*
+
+ # Copy readme files
+ src=$source_folder/$ide/$readme
+ target=$ports_folder/$mcu/$ide/$readme
+ #[ -f "$target" ] || continue
+ echo "$src -> $target"
+ rm -f $target
+ cp -f $src $target
+
+ # String replacement
+ sed -i "s/$source_string/$target_string_pre${mcu: -2}/g" $target
+ done
+done
+
+# Copy CMakeLists files
+for ide in $source_src_ide;
+do
+ for mcu in $target_src_mcu;
+ do
+ # Copy CMakeList files ac6
+ src=$source_folder/ac6/$cmake
+ target=$ports_folder/$mcu/ac6/$cmake
+ #[ -f "$target" ] || continue
+ echo "$src -> $target"
+ rm -f $target
+ cp -f $src $target
+
+ # Copy CMakeList files gnu
+ src=$source_folder/gnu/$cmake
+ target=$ports_folder/$mcu/gnu/$cmake
+ #[ -f "$target" ] || continue
+ echo "$src -> $target"
+ rm -f $target
+ cp -f $src $target
+ done
+done \ No newline at end of file
diff --git a/scripts/copy_module_armv7_m.sh b/scripts/copy_module_armv7_m.sh
new file mode 100755
index 00000000..8dbd834c
--- /dev/null
+++ b/scripts/copy_module_armv7_m.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# There is only one tx_port.h file that covers three architectures: M3/M4/M7 and four tools: ac5/ac6/gnu/iar.
+# This file is in threadx/ports_module/armv7-m/inc. We are going to ignore GHS.
+
+set -e
+
+ports_folder="ports_arch/ARMv7-M/threadx"
+ports_file_list="tx_thread_context_restore tx_thread_context_save tx_thread_interrupt_control tx_thread_interrupt_disable tx_thread_interrupt_restore tx_thread_stack_build tx_thread_system_return tx_timer_interrupt"
+ports_module_folder="ports_module"
+source_folder="ports_arch/ARMv7-M/threadx_modules"
+target_mcu="cortex_m3 cortex_m4 cortex_m7"
+source_inc_folder="$source_folder/inc"
+target_inc_folder="inc"
+target_ide="ac5 ac6 gnu iar"
+source_common_folder="common/module_manager/src"
+target_common_folder="module_manager"
+source_string="Cortex-Mx"
+target_string_pre="Cortex-M"
+
+
+cd $(dirname `realpath $0`)/..
+
+# Copy IDE specific files
+for mcu in $target_mcu;
+do
+ for ide in $target_ide;
+ do
+ for d in $(ls $source_folder/$ide);
+ do
+ # Copy specific files
+ source=$source_folder/$ide/$d
+ target=$ports_module_folder/$mcu/$ide/$d
+ echo "$source -> $target"
+ rm -rf $target
+ cp -rf $source $target
+
+ # String replacement
+ find $target -type f -exec sed -i "s/$source_string/$target_string_pre${mcu: -1}/g" {} \;
+ done
+
+ # copy common inc directory containing unified tx_port.h
+ target=$ports_module_folder/$mcu/$ide/$target_inc_folder
+ echo "$source_inc_folder -> $target"
+ cp -rf $source_inc_folder/* $target
+ find $target -type f -exec sed -i "s/$source_string/$target_string_pre${mcu: -1}/g" {} \;
+
+ # Copy common files
+ source=$source_folder/$source_common_folder;
+ target=$ports_module_folder/$mcu/$ide/$target_common_folder
+ echo "$source -> $target"
+ cp -rf $source $target
+
+ source=$ports_folder/$ide/src;
+ echo "$source -> $target"
+ for f in $ports_file_list;
+ do
+ cp $source/$f.* $target/src
+ done
+
+ # String replacement
+ find $target -type f -exec sed -i "s/$source_string/$target_string_pre${mcu: -1}/g" {} \;
+ done
+done \ No newline at end of file