1
0
mirror of https://github.com/azure-rtos/threadx synced 2025-01-16 07:42:57 +08:00

Release ARMv7-M and ARMv8-M architecture ports (#249)

* Release ARMv7-M and ARMv8-M architecture ports

* Add a pipeline to check ports_arch
This commit is contained in:
TiejunZhou 2023-04-18 18:11:20 +08:00 committed by GitHub
parent d64ef2ab06
commit 23680f5e5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
179 changed files with 47913 additions and 0 deletions

45
.github/workflows/ports_arch_check.yml vendored Normal file
View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,85 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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
// }

View File

@ -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
// }

View File

@ -0,0 +1,85 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#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
// }

View File

@ -0,0 +1,85 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#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
// }

View File

@ -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
// }

View File

@ -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

View File

@ -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
// }

View File

@ -0,0 +1,99 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** 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
// }

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,74 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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
)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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__ = .;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
// }

View File

@ -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
// }

View File

@ -0,0 +1,85 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#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
// }

View File

@ -0,0 +1,85 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#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
// }

View File

@ -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
// }

View File

@ -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

View File

@ -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
// }

View File

@ -0,0 +1,99 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** 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
// }

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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};

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,174 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** 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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More