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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

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

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