mirror of
https://github.com/azure-rtos/threadx
synced 2025-01-16 07:42:57 +08:00
Release ARMv7-M and ARMv8-M architecture ports (#249)
* Release ARMv7-M and ARMv8-M architecture ports * Add a pipeline to check ports_arch
This commit is contained in:
parent
d64ef2ab06
commit
23680f5e5f
45
.github/workflows/ports_arch_check.yml
vendored
Normal file
45
.github/workflows/ports_arch_check.yml
vendored
Normal 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
|
||||
|
||||
|
||||
|
5
ports_arch/ARMv7-M/README.md
Normal file
5
ports_arch/ARMv7-M/README.md
Normal 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.
|
||||
|
231
ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx.bat
Normal file
231
ports_arch/ARMv7-M/threadx/ac5/example_build/build_threadx.bat
Normal 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
|
@ -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
|
||||
|
369
ports_arch/ARMv7-M/threadx/ac5/example_build/sample_threadx.c
Normal file
369
ports_arch/ARMv7-M/threadx/ac5/example_build/sample_threadx.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
208
ports_arch/ARMv7-M/threadx/ac5/readme_threadx.txt
Normal file
208
ports_arch/ARMv7-M/threadx/ac5/readme_threadx.txt
Normal 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
|
||||
|
@ -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
|
85
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_save.s
Normal file
85
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_context_save.s
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
325
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s
Normal file
325
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s
Normal 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
|
131
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_stack_build.s
Normal file
131
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_stack_build.s
Normal 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
|
91
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_system_return.s
Normal file
91
ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_system_return.s
Normal 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
|
259
ports_arch/ARMv7-M/threadx/ac5/src/tx_timer_interrupt.s
Normal file
259
ports_arch/ARMv7-M/threadx/ac5/src/tx_timer_interrupt.s
Normal 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
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
150
ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.cproject
Normal file
150
ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.cproject
Normal 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=""${workspace_loc:/${ProjName}/inc_generic}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_port}""/>
|
||||
|
||||
</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>
|
48
ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.project
Normal file
48
ports_arch/ARMv7-M/threadx/ac6/example_build/tx/.project
Normal 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>
|
209
ports_arch/ARMv7-M/threadx/ac6/readme_threadx.txt
Normal file
209
ports_arch/ARMv7-M/threadx/ac6/readme_threadx.txt
Normal 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
|
||||
|
723
ports_arch/ARMv7-M/threadx/ac6/src/tx_misra.S
Normal file
723
ports_arch/ARMv7-M/threadx/ac6/src/tx_misra.S
Normal file
@ -0,0 +1,723 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** ThreadX MISRA Compliance */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
#define SHT_PROGBITS 0x1
|
||||
|
||||
.global __aeabi_memset
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_thread_interrupt_disable
|
||||
.global _tx_thread_interrupt_restore
|
||||
.global _tx_thread_stack_analyze
|
||||
.global _tx_thread_stack_error_handler
|
||||
.global _tx_thread_system_state
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_trace_buffer_current_ptr
|
||||
.global _tx_trace_buffer_end_ptr
|
||||
.global _tx_trace_buffer_start_ptr
|
||||
.global _tx_trace_event_enable_bits
|
||||
.global _tx_trace_full_notify_function
|
||||
.global _tx_trace_header_ptr
|
||||
#endif
|
||||
|
||||
.global _tx_misra_always_true
|
||||
.global _tx_misra_block_pool_to_uchar_pointer_convert
|
||||
.global _tx_misra_byte_pool_to_uchar_pointer_convert
|
||||
.global _tx_misra_char_to_uchar_pointer_convert
|
||||
.global _tx_misra_const_char_to_char_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_entry_to_uchar_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_indirect_void_to_uchar_pointer_convert
|
||||
.global _tx_misra_memset
|
||||
.global _tx_misra_message_copy
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_object_to_uchar_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_pointer_to_ulong_convert
|
||||
.global _tx_misra_status_get
|
||||
.global _tx_misra_thread_stack_check
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_time_stamp_get
|
||||
#endif
|
||||
.global _tx_misra_timer_indirect_to_void_pointer_convert
|
||||
.global _tx_misra_timer_pointer_add
|
||||
.global _tx_misra_timer_pointer_dif
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_trace_event_insert
|
||||
#endif
|
||||
.global _tx_misra_uchar_pointer_add
|
||||
.global _tx_misra_uchar_pointer_dif
|
||||
.global _tx_misra_uchar_pointer_sub
|
||||
.global _tx_misra_uchar_to_align_type_pointer_convert
|
||||
.global _tx_misra_uchar_to_block_pool_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_uchar_to_entry_pointer_convert
|
||||
.global _tx_misra_uchar_to_header_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
|
||||
.global _tx_misra_uchar_to_indirect_uchar_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_uchar_to_object_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_uchar_to_void_pointer_convert
|
||||
.global _tx_misra_ulong_pointer_add
|
||||
.global _tx_misra_ulong_pointer_dif
|
||||
.global _tx_misra_ulong_pointer_sub
|
||||
.global _tx_misra_ulong_to_pointer_convert
|
||||
.global _tx_misra_ulong_to_thread_pointer_convert
|
||||
.global _tx_misra_user_timer_pointer_get
|
||||
.global _tx_misra_void_to_block_pool_pointer_convert
|
||||
.global _tx_misra_void_to_byte_pool_pointer_convert
|
||||
.global _tx_misra_void_to_event_flags_pointer_convert
|
||||
.global _tx_misra_void_to_indirect_uchar_pointer_convert
|
||||
.global _tx_misra_void_to_mutex_pointer_convert
|
||||
.global _tx_misra_void_to_queue_pointer_convert
|
||||
.global _tx_misra_void_to_semaphore_pointer_convert
|
||||
.global _tx_misra_void_to_thread_pointer_convert
|
||||
.global _tx_misra_void_to_uchar_pointer_convert
|
||||
.global _tx_misra_void_to_ulong_pointer_convert
|
||||
.global _tx_misra_ipsr_get
|
||||
.global _tx_misra_control_get
|
||||
.global _tx_misra_control_set
|
||||
#ifdef __ARM_FP
|
||||
.global _tx_misra_fpccr_get
|
||||
.global _tx_misra_vfp_touch
|
||||
#endif
|
||||
|
||||
.global _tx_misra_event_flags_group_not_used
|
||||
.global _tx_misra_event_flags_set_notify_not_used
|
||||
.global _tx_misra_queue_not_used
|
||||
.global _tx_misra_queue_send_notify_not_used
|
||||
.global _tx_misra_semaphore_not_used
|
||||
.global _tx_misra_semaphore_put_notify_not_used
|
||||
.global _tx_misra_thread_entry_exit_notify_not_used
|
||||
.global _tx_misra_thread_not_used
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
.thumb_func
|
||||
_tx_misra_memset:
|
||||
PUSH {R4,LR}
|
||||
MOVS R4,R0
|
||||
MOVS R0,R2
|
||||
MOVS R2,R1
|
||||
MOVS R1,R0
|
||||
MOVS R0,R4
|
||||
BL __aeabi_memset
|
||||
POP {R4,PC} // return
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_uchar_pointer_add:
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_uchar_pointer_sub:
|
||||
RSBS R1,R1,#+0
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_uchar_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
/** */
|
||||
/** This single function serves all of the below prototypes. */
|
||||
/** */
|
||||
/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
|
||||
/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
|
||||
/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
|
||||
/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
|
||||
/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
|
||||
/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
|
||||
/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
|
||||
/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
|
||||
/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
|
||||
/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
|
||||
/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
|
||||
/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
|
||||
/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
|
||||
/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
|
||||
/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
|
||||
/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
|
||||
/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
|
||||
/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
|
||||
/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
|
||||
/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
|
||||
/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
|
||||
/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
|
||||
/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
|
||||
/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
|
||||
/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
|
||||
/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
|
||||
/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
|
||||
/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
|
||||
/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
|
||||
/** */
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_pointer_to_ulong_convert:
|
||||
_tx_misra_ulong_to_pointer_convert:
|
||||
_tx_misra_indirect_void_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_indirect_uchar_pointer_convert:
|
||||
_tx_misra_block_pool_to_uchar_pointer_convert:
|
||||
_tx_misra_void_to_block_pool_pointer_convert:
|
||||
_tx_misra_void_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_block_pool_pointer_convert:
|
||||
_tx_misra_void_to_indirect_uchar_pointer_convert:
|
||||
_tx_misra_void_to_byte_pool_pointer_convert:
|
||||
_tx_misra_byte_pool_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_align_type_pointer_convert:
|
||||
_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
|
||||
_tx_misra_void_to_event_flags_pointer_convert:
|
||||
_tx_misra_void_to_ulong_pointer_convert:
|
||||
_tx_misra_void_to_mutex_pointer_convert:
|
||||
_tx_misra_void_to_queue_pointer_convert:
|
||||
_tx_misra_void_to_semaphore_pointer_convert:
|
||||
_tx_misra_uchar_to_void_pointer_convert:
|
||||
_tx_misra_ulong_to_thread_pointer_convert:
|
||||
_tx_misra_timer_indirect_to_void_pointer_convert:
|
||||
_tx_misra_const_char_to_char_pointer_convert:
|
||||
_tx_misra_void_to_thread_pointer_convert:
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
_tx_misra_object_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_object_pointer_convert:
|
||||
_tx_misra_uchar_to_header_pointer_convert:
|
||||
_tx_misra_uchar_to_entry_pointer_convert:
|
||||
_tx_misra_entry_to_uchar_pointer_convert:
|
||||
#endif
|
||||
_tx_misra_char_to_uchar_pointer_convert:
|
||||
_tx_misra_event_flags_group_not_used:
|
||||
_tx_misra_event_flags_set_notify_not_used:
|
||||
_tx_misra_queue_not_used:
|
||||
_tx_misra_queue_send_notify_not_used:
|
||||
_tx_misra_semaphore_not_used:
|
||||
_tx_misra_semaphore_put_notify_not_used:
|
||||
_tx_misra_thread_entry_exit_notify_not_used:
|
||||
_tx_misra_thread_not_used:
|
||||
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ulong_pointer_add:
|
||||
ADD R0,R0,R1, LSL #+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ulong_pointer_sub:
|
||||
MVNS R2,#+3
|
||||
MULS R1,R2,R1
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ulong_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
ASRS R0,R0,#+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
|
||||
/** UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_message_copy:
|
||||
PUSH {R4,R5}
|
||||
LDR R3,[R0, #+0]
|
||||
LDR R4,[R1, #+0]
|
||||
LDR R5,[R3, #+0]
|
||||
STR R5,[R4, #+0]
|
||||
ADDS R4,R4,#+4
|
||||
ADDS R3,R3,#+4
|
||||
CMP R2,#+2
|
||||
BCC.N _tx_misra_message_copy_0
|
||||
SUBS R2,R2,#+1
|
||||
B.N _tx_misra_message_copy_1
|
||||
_tx_misra_message_copy_2:
|
||||
LDR R5,[R3, #+0]
|
||||
STR R5,[R4, #+0]
|
||||
ADDS R4,R4,#+4
|
||||
ADDS R3,R3,#+4
|
||||
SUBS R2,R2,#+1
|
||||
_tx_misra_message_copy_1:
|
||||
CMP R2,#+0
|
||||
BNE.N _tx_misra_message_copy_2
|
||||
_tx_misra_message_copy_0:
|
||||
STR R3,[R0, #+0]
|
||||
STR R4,[R1, #+0]
|
||||
POP {R4,R5}
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
|
||||
/** TX_TIMER_INTERNAL **ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_timer_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
ASRS R0,R0,#+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
|
||||
/** **ptr1, ULONG size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_timer_pointer_add:
|
||||
ADD R0,R0,R1, LSL #+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
|
||||
/** *internal_timer, TX_TIMER **user_timer); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_user_timer_pointer_get:
|
||||
SUBS R0,#8
|
||||
STR R0,[R1, #+0]
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
|
||||
/** VOID **highest_stack); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_thread_stack_check:
|
||||
PUSH {R3-R5,LR}
|
||||
MOVS R4,R0
|
||||
MOVS R5,R1
|
||||
BL _tx_thread_interrupt_disable
|
||||
CMP R4,#+0
|
||||
BEQ.N _tx_misra_thread_stack_check_0
|
||||
LDR R1,[R4, #+0]
|
||||
LDR R2,=0x54485244
|
||||
CMP R1,R2
|
||||
BNE.N _tx_misra_thread_stack_check_0
|
||||
LDR R1,[R4, #+8]
|
||||
LDR R2,[R5, #+0]
|
||||
CMP R1,R2
|
||||
BCS.N _tx_misra_thread_stack_check_1
|
||||
LDR R1,[R4, #+8]
|
||||
STR R1,[R5, #+0]
|
||||
_tx_misra_thread_stack_check_1:
|
||||
LDR R1,[R4, #+12]
|
||||
LDR R1,[R1, #+0]
|
||||
CMP R1,#-269488145
|
||||
BNE.N _tx_misra_thread_stack_check_2
|
||||
LDR R1,[R4, #+16]
|
||||
LDR R1,[R1, #+1]
|
||||
CMP R1,#-269488145
|
||||
BNE.N _tx_misra_thread_stack_check_2
|
||||
LDR R1,[R5, #+0]
|
||||
LDR R2,[R4, #+12]
|
||||
CMP R1,R2
|
||||
BCS.N _tx_misra_thread_stack_check_3
|
||||
_tx_misra_thread_stack_check_2:
|
||||
BL _tx_thread_interrupt_restore
|
||||
MOVS R0,R4
|
||||
BL _tx_thread_stack_error_handler
|
||||
BL _tx_thread_interrupt_disable
|
||||
_tx_misra_thread_stack_check_3:
|
||||
LDR R1,[R5, #+0]
|
||||
LDR R1,[R1, #-4]
|
||||
CMP R1,#-269488145
|
||||
BEQ.N _tx_misra_thread_stack_check_0
|
||||
BL _tx_thread_interrupt_restore
|
||||
MOVS R0,R4
|
||||
BL _tx_thread_stack_analyze
|
||||
BL _tx_thread_interrupt_disable
|
||||
_tx_misra_thread_stack_check_0:
|
||||
BL _tx_thread_interrupt_restore
|
||||
POP {R0,R4,R5,PC} // return
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
|
||||
/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
|
||||
/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_trace_event_insert:
|
||||
PUSH {R3-R7,LR}
|
||||
LDR.N R4,DataTable2_1
|
||||
LDR R4,[R4, #+0]
|
||||
CMP R4,#+0
|
||||
BEQ.N _tx_misra_trace_event_insert_0
|
||||
LDR.N R5,DataTable2_2
|
||||
LDR R5,[R5, #+0]
|
||||
LDR R6,[SP, #+28]
|
||||
TST R5,R6
|
||||
BEQ.N _tx_misra_trace_event_insert_0
|
||||
LDR.N R5,DataTable2_3
|
||||
LDR R5,[R5, #+0]
|
||||
LDR.N R6,DataTable2_4
|
||||
LDR R6,[R6, #+0]
|
||||
CMP R5,#+0
|
||||
BNE.N _tx_misra_trace_event_insert_1
|
||||
LDR R5,[R6, #+44]
|
||||
LDR R7,[R6, #+60]
|
||||
LSLS R7,R7,#+16
|
||||
ORRS R7,R7,#0x80000000
|
||||
ORRS R5,R7,R5
|
||||
B.N _tx_misra_trace_event_insert_2
|
||||
_tx_misra_trace_event_insert_1:
|
||||
CMP R5,#-252645136
|
||||
BCS.N _tx_misra_trace_event_insert_3
|
||||
MOVS R5,R6
|
||||
MOVS R6,#-1
|
||||
B.N _tx_misra_trace_event_insert_2
|
||||
_tx_misra_trace_event_insert_3:
|
||||
MOVS R6,#-252645136
|
||||
MOVS R5,#+0
|
||||
_tx_misra_trace_event_insert_2:
|
||||
STR R6,[R4, #+0]
|
||||
STR R5,[R4, #+4]
|
||||
STR R0,[R4, #+8]
|
||||
LDR R0,[SP, #+32]
|
||||
STR R0,[R4, #+12]
|
||||
STR R1,[R4, #+16]
|
||||
STR R2,[R4, #+20]
|
||||
STR R3,[R4, #+24]
|
||||
LDR R0,[SP, #+24]
|
||||
STR R0,[R4, #+28]
|
||||
ADDS R4,R4,#+32
|
||||
LDR.N R0,DataTable2_5
|
||||
LDR R0,[R0, #+0]
|
||||
CMP R4,R0
|
||||
BCC.N _tx_misra_trace_event_insert_4
|
||||
LDR.N R0,DataTable2_6
|
||||
LDR R4,[R0, #+0]
|
||||
LDR.N R0,DataTable2_1
|
||||
STR R4,[R0, #+0]
|
||||
LDR.N R0,DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
STR R4,[R0, #+32]
|
||||
LDR.N R0,DataTable2_8
|
||||
LDR R0,[R0, #+0]
|
||||
CMP R0,#+0
|
||||
BEQ.N _tx_misra_trace_event_insert_0
|
||||
LDR.N R0,DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
LDR.N R1,DataTable2_8
|
||||
LDR R1,[R1, #+0]
|
||||
BLX R1
|
||||
B.N _tx_misra_trace_event_insert_0
|
||||
_tx_misra_trace_event_insert_4:
|
||||
LDR.N R0,DataTable2_1
|
||||
STR R4,[R0, #+0]
|
||||
LDR.N R0,DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
STR R4,[R0, #+32]
|
||||
_tx_misra_trace_event_insert_0:
|
||||
POP {R0,R4-R7,PC} // return
|
||||
|
||||
|
||||
.data
|
||||
DataTable2_1:
|
||||
.word _tx_trace_buffer_current_ptr
|
||||
|
||||
.data
|
||||
DataTable2_2:
|
||||
.word _tx_trace_event_enable_bits
|
||||
|
||||
.data
|
||||
DataTable2_5:
|
||||
.word _tx_trace_buffer_end_ptr
|
||||
|
||||
.data
|
||||
DataTable2_6:
|
||||
.word _tx_trace_buffer_start_ptr
|
||||
|
||||
.data
|
||||
DataTable2_7:
|
||||
.word _tx_trace_header_ptr
|
||||
|
||||
.data
|
||||
DataTable2_8:
|
||||
.word _tx_trace_full_notify_function
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_time_stamp_get(VOID); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_time_stamp_get:
|
||||
MOVS R0,#+0
|
||||
BX LR // return
|
||||
|
||||
#endif
|
||||
|
||||
.data
|
||||
DataTable2_3:
|
||||
.word _tx_thread_system_state
|
||||
|
||||
.data
|
||||
DataTable2_4:
|
||||
.word _tx_thread_current_ptr
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_always_true(void); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_always_true:
|
||||
MOVS R0,#+1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_status_get(UINT status); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_status_get:
|
||||
MOVS R0,#+0
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ipsr_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ipsr_get:
|
||||
MRS R0, IPSR
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_control_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_control_get:
|
||||
MRS R0, CONTROL
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** void _tx_misra_control_set(ULONG value); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_control_set:
|
||||
MSR CONTROL, R0
|
||||
BX LR // return
|
||||
|
||||
|
||||
#ifdef __ARM_FP
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_fpccr_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_fpccr_get:
|
||||
LDR r0, =0xE000EF34 // Build FPCCR address
|
||||
LDR r0, [r0] // Load FPCCR value
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** void _tx_misra_vfp_touch(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_vfp_touch:
|
||||
vmov.f32 s0, s0
|
||||
BX LR // return
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
.data
|
||||
.word 0
|
@ -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
|
||||
// }
|
89
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_save.S
Normal file
89
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_context_save.S
Normal 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
|
||||
// }
|
@ -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
|
||||
// }
|
@ -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
|
||||
// }
|
@ -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
|
||||
// }
|
331
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S
Normal file
331
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S
Normal 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
|
139
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_stack_build.S
Normal file
139
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_stack_build.S
Normal 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
|
||||
// }
|
99
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S
Normal file
99
ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S
Normal 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
|
||||
// }
|
261
ports_arch/ARMv7-M/threadx/ac6/src/tx_timer_interrupt.S
Normal file
261
ports_arch/ARMv7-M/threadx/ac6/src/tx_timer_interrupt.S
Normal 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
|
369
ports_arch/ARMv7-M/threadx/ghs/example_build/sample_threadx.c
Normal file
369
ports_arch/ARMv7-M/threadx/ghs/example_build/sample_threadx.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
765
ports_arch/ARMv7-M/threadx/ghs/inc/tx_el.h
Normal file
765
ports_arch/ARMv7-M/threadx/ghs/inc/tx_el.h
Normal file
@ -0,0 +1,765 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** ThreadX/GHS Event Log (EL) */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_el.h PORTABLE C/GHS */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX event log functions for the GHS MULTI */
|
||||
/* EventAnalyzer. It is assumed that tx_api.h and tx_port.h have */
|
||||
/* already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_EL_H
|
||||
#define TX_EL_H
|
||||
|
||||
|
||||
/* Define Event Log specific data definitions. */
|
||||
|
||||
#define TX_EL_VERSION_ID 2 /* Event log version ID */
|
||||
#define TX_EL_HEADER_SIZE 24 /* Event log header size */
|
||||
#define TX_EL_TNIS 16 /* Number of thread names supported */
|
||||
/* If the application needs to */
|
||||
/* track more thread names, just */
|
||||
/* increase this number and re- */
|
||||
/* build the ThreadX library. */
|
||||
#define TX_EL_TNI_ENTRY_SIZE 44 /* Thread name entries are 44 bytes */
|
||||
#define TX_EL_TNI_NAME_SIZE 34 /* Thread name size in TNI */
|
||||
#define TX_EL_NO_MORE_TNI_ROOM 1 /* Error return from thread register*/
|
||||
#define TX_EL_NAME_NOT_FOUND 2 /* Error return from un-register */
|
||||
#define TX_EL_EVENT_SIZE 32 /* Number of bytes in each event */
|
||||
#define TX_EL_VALID_ENTRY 1 /* Valid log entry */
|
||||
#define TX_EL_INVALID_ENTRY 0 /* Invalid log entry */
|
||||
|
||||
|
||||
/* Define necessary offsets. */
|
||||
|
||||
#define TX_EL_TNI_VALID_OFFSET 34
|
||||
#define TX_EL_TNI_THREAD_ID_OFFSET 36
|
||||
#define TX_EL_TNI_THREAD_PRIORITY_OFF 40
|
||||
#define TX_EL_EVENT_TYPE_OFFSET 0
|
||||
#define TX_EL_EVENT_SUBTYPE_OFFSET 2
|
||||
#define TX_EL_EVENT_TIME_UPPER_OFFSET 4
|
||||
#define TX_EL_EVENT_TIME_LOWER_OFFSET 8
|
||||
#define TX_EL_EVENT_THREAD_OFFSET 12
|
||||
#define TX_EL_EVENT_INFO_1_OFFSET 16
|
||||
#define TX_EL_EVENT_INFO_2_OFFSET 20
|
||||
#define TX_EL_EVENT_INFO_3_OFFSET 24
|
||||
#define TX_EL_EVENT_INFO_4_OFFSET 28
|
||||
|
||||
|
||||
/* Undefine constants that might be been defined previously by tx_api.h. */
|
||||
|
||||
#undef TX_EL_INITIALIZE
|
||||
#undef TX_EL_THREAD_REGISTER
|
||||
#undef TX_EL_THREAD_UNREGISTER
|
||||
#undef TX_EL_THREAD_STATUS_CHANGE_INSERT
|
||||
#undef TX_EL_BYTE_ALLOCATE_INSERT
|
||||
#undef TX_EL_BYTE_POOL_CREATE_INSERT
|
||||
#undef TX_EL_BYTE_POOL_DELETE_INSERT
|
||||
#undef TX_EL_BYTE_RELEASE_INSERT
|
||||
#undef TX_EL_BLOCK_ALLOCATE_INSERT
|
||||
#undef TX_EL_BLOCK_POOL_CREATE_INSERT
|
||||
#undef TX_EL_BLOCK_POOL_DELETE_INSERT
|
||||
#undef TX_EL_BLOCK_RELEASE_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_CREATE_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_DELETE_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_GET_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_SET_INSERT
|
||||
#undef TX_EL_INTERRUPT_CONTROL_INSERT
|
||||
#undef TX_EL_QUEUE_CREATE_INSERT
|
||||
#undef TX_EL_QUEUE_DELETE_INSERT
|
||||
#undef TX_EL_QUEUE_FLUSH_INSERT
|
||||
#undef TX_EL_QUEUE_RECEIVE_INSERT
|
||||
#undef TX_EL_QUEUE_SEND_INSERT
|
||||
#undef TX_EL_SEMAPHORE_CREATE_INSERT
|
||||
#undef TX_EL_SEMAPHORE_DELETE_INSERT
|
||||
#undef TX_EL_SEMAPHORE_GET_INSERT
|
||||
#undef TX_EL_SEMAPHORE_PUT_INSERT
|
||||
#undef TX_EL_THREAD_CREATE_INSERT
|
||||
#undef TX_EL_THREAD_DELETE_INSERT
|
||||
#undef TX_EL_THREAD_IDENTIFY_INSERT
|
||||
#undef TX_EL_THREAD_PREEMPTION_CHANGE_INSERT
|
||||
#undef TX_EL_THREAD_PRIORITY_CHANGE_INSERT
|
||||
#undef TX_EL_THREAD_RELINQUISH_INSERT
|
||||
#undef TX_EL_THREAD_RESUME_INSERT
|
||||
#undef TX_EL_THREAD_SLEEP_INSERT
|
||||
#undef TX_EL_THREAD_SUSPEND_INSERT
|
||||
#undef TX_EL_THREAD_TERMINATE_INSERT
|
||||
#undef TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT
|
||||
#undef TX_EL_TIME_GET_INSERT
|
||||
#undef TX_EL_TIME_SET_INSERT
|
||||
#undef TX_EL_TIMER_ACTIVATE_INSERT
|
||||
#undef TX_EL_TIMER_CHANGE_INSERT
|
||||
#undef TX_EL_TIMER_CREATE_INSERT
|
||||
#undef TX_EL_TIMER_DEACTIVATE_INSERT
|
||||
#undef TX_EL_TIMER_DELETE_INSERT
|
||||
#undef TX_EL_BLOCK_POOL_INFO_GET_INSERT
|
||||
#undef TX_EL_BLOCK_POOL_PRIORITIZE_INSERT
|
||||
#undef TX_EL_BYTE_POOL_INFO_GET_INSERT
|
||||
#undef TX_EL_BYTE_POOL_PRIORITIZE_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_INFO_GET_INSERT
|
||||
#undef TX_EL_MUTEX_CREATE_INSERT
|
||||
#undef TX_EL_MUTEX_DELETE_INSERT
|
||||
#undef TX_EL_MUTEX_GET_INSERT
|
||||
#undef TX_EL_MUTEX_INFO_GET_INSERT
|
||||
#undef TX_EL_MUTEX_PRIORITIZE_INSERT
|
||||
#undef TX_EL_MUTEX_PUT_INSERT
|
||||
#undef TX_EL_QUEUE_INFO_GET_INSERT
|
||||
#undef TX_EL_QUEUE_FRONT_SEND_INSERT
|
||||
#undef TX_EL_QUEUE_PRIORITIZE_INSERT
|
||||
#undef TX_EL_SEMAPHORE_INFO_GET_INSERT
|
||||
#undef TX_EL_SEMAPHORE_PRIORITIZE_INSERT
|
||||
#undef TX_EL_THREAD_INFO_GET_INSERT
|
||||
#undef TX_EL_THREAD_WAIT_ABORT_INSERT
|
||||
#undef TX_EL_TIMER_INFO_GET_INSERT
|
||||
#undef TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT
|
||||
#undef TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_QUEUE_SEND_NOTIFY_INSERT
|
||||
#undef TX_EL_SEMAPHORE_CEILING_PUT_INSERT
|
||||
#undef TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT
|
||||
#undef TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT
|
||||
#undef TX_EL_THREAD_RESET_INSERT
|
||||
#undef TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
#undef TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT
|
||||
#undef TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT
|
||||
#undef TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
|
||||
/* Define Event Types. */
|
||||
|
||||
#define TX_EL_THREAD_CHANGE 1
|
||||
#define TX_EL_INTERRUPT 2
|
||||
#define TX_EL_THREADX_CALL 3
|
||||
#define TX_EL_USER_EVENT 4
|
||||
#define TX_EL_THREAD_STATUS_CHANGE 5
|
||||
#define TX_EL_REFRESH 6 /* Not implemented */
|
||||
#define TX_EL_TIMER 7 /* Not implemented */
|
||||
#define TX_EL_TIMESOURCE_DELTA 8 /* Not implemented */
|
||||
|
||||
|
||||
/* Define TX_EL_THREADX_CALL event sub-types. */
|
||||
|
||||
#define TX_EL_BYTE_ALLOCATE 0
|
||||
#define TX_EL_BYTE_POOL_CREATE 1
|
||||
#define TX_EL_BYTE_POOL_DELETE 2
|
||||
#define TX_EL_BYTE_RELEASE 3
|
||||
#define TX_EL_BLOCK_ALLOCATE 4
|
||||
#define TX_EL_BLOCK_POOL_CREATE 5
|
||||
#define TX_EL_BLOCK_POOL_DELETE 6
|
||||
#define TX_EL_BLOCK_RELEASE 7
|
||||
#define TX_EL_EVENT_FLAGS_CREATE 8
|
||||
#define TX_EL_EVENT_FLAGS_DELETE 9
|
||||
#define TX_EL_EVENT_FLAGS_GET 10
|
||||
#define TX_EL_EVENT_FLAGS_SET 11
|
||||
#define TX_EL_INTERRUPT_CONTROL 12
|
||||
#define TX_EL_QUEUE_CREATE 13
|
||||
#define TX_EL_QUEUE_DELETE 14
|
||||
#define TX_EL_QUEUE_FLUSH 15
|
||||
#define TX_EL_QUEUE_RECEIVE 16
|
||||
#define TX_EL_QUEUE_SEND 17
|
||||
#define TX_EL_SEMAPHORE_CREATE 18
|
||||
#define TX_EL_SEMAPHORE_DELETE 19
|
||||
#define TX_EL_SEMAPHORE_GET 20
|
||||
#define TX_EL_SEMAPHORE_PUT 21
|
||||
#define TX_EL_THREAD_CREATE 22
|
||||
#define TX_EL_THREAD_DELETE 23
|
||||
#define TX_EL_THREAD_IDENTIFY 24
|
||||
#define TX_EL_THREAD_PREEMPTION_CHANGE 25
|
||||
#define TX_EL_THREAD_PRIORITY_CHANGE 26
|
||||
#define TX_EL_THREAD_RELINQUISH 27
|
||||
#define TX_EL_THREAD_RESUME 28
|
||||
#define TX_EL_THREAD_SLEEP 29
|
||||
#define TX_EL_THREAD_SUSPEND 30
|
||||
#define TX_EL_THREAD_TERMINATE 31
|
||||
#define TX_EL_THREAD_TIME_SLICE_CHANGE 32
|
||||
#define TX_EL_TIME_GET 33
|
||||
#define TX_EL_TIME_SET 34
|
||||
#define TX_EL_TIMER_ACTIVATE 35
|
||||
#define TX_EL_TIMER_CHANGE 36
|
||||
#define TX_EL_TIMER_CREATE 37
|
||||
#define TX_EL_TIMER_DEACTIVATE 38
|
||||
#define TX_EL_TIMER_DELETE 39
|
||||
#define TX_EL_BLOCK_POOL_INFO_GET 40
|
||||
#define TX_EL_BLOCK_POOL_PRIORITIZE 41
|
||||
#define TX_EL_BYTE_POOL_INFO_GET 42
|
||||
#define TX_EL_BYTE_POOL_PRIORITIZE 43
|
||||
#define TX_EL_EVENT_FLAGS_INFO_GET 44
|
||||
#define TX_EL_MUTEX_CREATE 45
|
||||
#define TX_EL_MUTEX_DELETE 46
|
||||
#define TX_EL_MUTEX_GET 47
|
||||
#define TX_EL_MUTEX_INFO_GET 48
|
||||
#define TX_EL_MUTEX_PRIORITIZE 49
|
||||
#define TX_EL_MUTEX_PUT 50
|
||||
#define TX_EL_QUEUE_INFO_GET 51
|
||||
#define TX_EL_QUEUE_FRONT_SEND 52
|
||||
#define TX_EL_QUEUE_PRIORITIZE 53
|
||||
#define TX_EL_SEMAPHORE_INFO_GET 54
|
||||
#define TX_EL_SEMAPHORE_PRIORITIZE 55
|
||||
#define TX_EL_THREAD_INFO_GET 56
|
||||
#define TX_EL_THREAD_WAIT_ABORT 57
|
||||
#define TX_EL_TIMER_INFO_GET 58
|
||||
#define TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET 59
|
||||
#define TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET 60
|
||||
#define TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET 61
|
||||
#define TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET 62
|
||||
#define TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET 63
|
||||
#define TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET 64
|
||||
#define TX_EL_EVENT_FLAGS_SET_NOTIFY 65
|
||||
#define TX_EL_MUTEX_PERFORMANCE_INFO_GET 66
|
||||
#define TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET 67
|
||||
#define TX_EL_QUEUE_PERFORMANCE_INFO_GET 68
|
||||
#define TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET 69
|
||||
#define TX_EL_QUEUE_SEND_NOTIFY 70
|
||||
#define TX_EL_SEMAPHORE_CEILING_PUT 71
|
||||
#define TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET 72
|
||||
#define TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET 73
|
||||
#define TX_EL_SEMAPHORE_PUT_NOTIFY 74
|
||||
#define TX_EL_THREAD_ENTRY_EXIT_NOTIFY 75
|
||||
#define TX_EL_THREAD_RESET 76
|
||||
#define TX_EL_THREAD_PERFORMANCE_INFO_GET 77
|
||||
#define TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET 78
|
||||
#define TX_EL_THREAD_STACK_ERROR_NOTIFY 79
|
||||
#define TX_EL_TIMER_PERFORMANCE_INFO_GET 80
|
||||
#define TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET 81
|
||||
|
||||
|
||||
/* Define ThreadX sub-types. */
|
||||
|
||||
#define TX_EL_INTERRUPT_SUB_TYPE 1
|
||||
#define TX_EL_END_OF_INTERRUPT 3
|
||||
|
||||
|
||||
/* Define event logging filters, which may be used by the application program to
|
||||
dynamically enable/disable events in run-time. */
|
||||
|
||||
#define TX_EL_FILTER_STATUS_CHANGE 0x0001
|
||||
#define TX_EL_FILTER_INTERRUPTS 0x0002
|
||||
#define TX_EL_FILTER_THREAD_CALLS 0x0004
|
||||
#define TX_EL_FILTER_TIMER_CALLS 0x0008
|
||||
#define TX_EL_FILTER_EVENT_FLAG_CALLS 0x0010
|
||||
#define TX_EL_FILTER_SEMAPHORE_CALLS 0x0020
|
||||
#define TX_EL_FILTER_QUEUE_CALLS 0x0040
|
||||
#define TX_EL_FILTER_BLOCK_CALLS 0x0080
|
||||
#define TX_EL_FILTER_BYTE_CALLS 0x0100
|
||||
#define TX_EL_FILTER_MUTEX_CALLS 0x0200
|
||||
#define TX_EL_FILTER_ALL_EVENTS 0xFFFF
|
||||
#define TX_EL_ENABLE_ALL_EVENTS 0x0000
|
||||
|
||||
|
||||
/* Define filter macros that are inserted in-line with the other macros below. */
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_FILTERS
|
||||
#define TX_EL_NO_STATUS_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_STATUS_CHANGE)) {
|
||||
#define TX_EL_NO_INTERRUPT_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_INTERRUPTS)) {
|
||||
#define TX_EL_NO_THREAD_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_THREAD_CALLS)) {
|
||||
#define TX_EL_NO_TIMER_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_TIMER_CALLS)) {
|
||||
#define TX_EL_NO_EVENT_FLAG_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_EVENT_FLAG_CALLS)) {
|
||||
#define TX_EL_NO_SEMAPHORE_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_SEMAPHORE_CALLS)) {
|
||||
#define TX_EL_NO_QUEUE_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_QUEUE_CALLS)) {
|
||||
#define TX_EL_NO_BLOCK_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_BLOCK_CALLS)) {
|
||||
#define TX_EL_NO_BYTE_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_BYTE_CALLS)) {
|
||||
#define TX_EL_NO_MUTEX_EVENTS if (!(_tx_el_event_filter & TX_EL_FILTER_MUTEX_CALLS)) {
|
||||
#define TX_EL_END_FILTER }
|
||||
#else
|
||||
#define TX_EL_NO_STATUS_EVENTS
|
||||
#define TX_EL_NO_INTERRUPT_EVENTS
|
||||
#define TX_EL_NO_THREAD_EVENTS
|
||||
#define TX_EL_NO_TIMER_EVENTS
|
||||
#define TX_EL_NO_EVENT_FLAG_EVENTS
|
||||
#define TX_EL_NO_SEMAPHORE_EVENTS
|
||||
#define TX_EL_NO_QUEUE_EVENTS
|
||||
#define TX_EL_NO_BLOCK_EVENTS
|
||||
#define TX_EL_NO_BYTE_EVENTS
|
||||
#define TX_EL_NO_MUTEX_EVENTS
|
||||
#define TX_EL_END_FILTER
|
||||
#endif
|
||||
|
||||
/* Define externs and constants for non-event log source modules. This is for
|
||||
the in-line macros below. */
|
||||
|
||||
#ifndef TX_EL_SOURCE_CODE
|
||||
extern UCHAR *_tx_el_tni_start;
|
||||
extern UCHAR **_tx_el_current_event;
|
||||
extern UCHAR *_tx_el_event_area_start;
|
||||
extern UCHAR *_tx_el_event_area_end;
|
||||
extern UINT _tx_el_maximum_events;
|
||||
extern ULONG _tx_el_total_events;
|
||||
extern TX_THREAD *_tx_thread_current_ptr;
|
||||
extern UINT _tx_el_event_filter;
|
||||
extern ULONG _tx_el_time_base_upper;
|
||||
extern ULONG _tx_el_time_base_lower;
|
||||
|
||||
|
||||
/* Define macros for event logging functions. */
|
||||
|
||||
#define TX_EL_THREAD_CREATE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_THREAD_CREATE, thread_ptr, stack_start, stack_size, priority); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_SET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_DELETE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_DELETE, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_INFO_GET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_INFO_GET, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_THREAD_TIME_SLICE_CHANGE, thread_ptr, thread_ptr -> tx_thread_new_time_slice, new_time_slice); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_TERMINATE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_TERMINATE, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_SLEEP_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_SLEEP, timer_ticks); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_SUSPEND_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_SUSPEND, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_RELINQUISH_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_THREAD_RELINQUISH); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_RESUME_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_RESUME, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_PRIORITY_CHANGE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_THREAD_PRIORITY_CHANGE, thread_ptr, thread_ptr -> tx_thread_priority, new_priority); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_PREEMPTION_CHANGE_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_THREAD_PREEMPTION_CHANGE, thread_ptr, thread_ptr -> tx_thread_preempt_threshold, new_threshold); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_WAIT_ABORT_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_WAIT_ABORT, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_THREAD_ENTRY_EXIT_NOTIFY, thread_ptr, thread_entry_exit_notify); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_RESET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_RESET, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_PERFORMANCE_INFO_GET, thread_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_THREAD_STACK_ERROR_NOTIFY, stack_error_handler); TX_EL_END_FILTER
|
||||
#define TX_EL_TIME_SET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIME_SET, new_time); TX_EL_END_FILTER
|
||||
#define TX_EL_TIME_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIME_GET, _tx_timer_system_clock); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_DELETE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_DELETE, timer_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_CREATE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_TIMER_CREATE, timer_ptr, initial_ticks, reschedule_ticks, auto_activate); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_CHANGE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_TIMER_CHANGE, timer_ptr, initial_ticks, reschedule_ticks); TX_EL_END_FILTER
|
||||
#define TX_EL_THREAD_IDENTIFY_INSERT TX_EL_NO_THREAD_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_THREAD_IDENTIFY); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_DEACTIVATE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_DEACTIVATE, timer_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_ACTIVATE_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_ACTIVATE, timer_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_INFO_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_INFO_GET, timer_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_TIMER_PERFORMANCE_INFO_GET, timer_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_TIMER_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_PUT_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_GET, semaphore_ptr, semaphore_ptr -> tx_semaphore_count); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_DELETE_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_DELETE, semaphore_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_CREATE_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_CREATE, semaphore_ptr, initial_count); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_INFO_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_INFO_GET, semaphore_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_PRIORITIZE_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_PRIORITIZE, semaphore_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_CEILING_PUT_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, ceiling); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET, semaphore_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT TX_EL_NO_SEMAPHORE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_SEMAPHORE_PUT_NOTIFY, semaphore_ptr, semaphore_put_notify); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_FRONT_SEND_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_FRONT_SEND, queue_ptr, source_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_SEND_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_SEND, queue_ptr, source_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_RECEIVE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_RECEIVE, queue_ptr, destination_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_FLUSH_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_FLUSH, queue_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_DELETE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_DELETE, queue_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_CREATE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_QUEUE_CREATE, queue_ptr, queue_start, queue_size, message_size); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_INFO_GET_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_INFO_GET, queue_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_PRIORITIZE_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_PRIORITIZE, queue_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_QUEUE_PERFORMANCE_INFO_GET, queue_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_QUEUE_SEND_NOTIFY_INSERT TX_EL_NO_QUEUE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_QUEUE_SEND_NOTIFY, queue_ptr, queue_send_notify); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_EVENT_FLAGS_GET, group_ptr, requested_flags, get_option); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_DELETE_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_DELETE, group_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_CREATE_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_CREATE, group_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_INFO_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_INFO_GET, group_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET, group_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT TX_EL_NO_EVENT_FLAG_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_EVENT_FLAGS_SET_NOTIFY, group_ptr, events_set_notify); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_RELEASE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_BYTE_RELEASE, pool_ptr, memory_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_POOL_DELETE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_DELETE, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_POOL_CREATE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_BYTE_POOL_CREATE, pool_ptr, pool_start, pool_size); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_POOL_INFO_GET_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_INFO_GET, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_POOL_PRIORITIZE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_PRIORITIZE, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_ALLOCATE_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_BYTE_ALLOCATE, pool_ptr, memory_ptr, memory_size); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_BYTE_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_RELEASE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_BLOCK_RELEASE, pool_ptr, block_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_POOL_DELETE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_DELETE, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_POOL_CREATE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(TX_EL_BLOCK_POOL_CREATE, pool_ptr, pool_start, pool_size, block_size); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_POOL_INFO_GET_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_INFO_GET, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_POOL_PRIORITIZE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_PRIORITIZE, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_ALLOCATE_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_BLOCK_ALLOCATE, pool_ptr, block_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET, pool_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_BLOCK_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_CREATE_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_MUTEX_CREATE, mutex_ptr, inherit); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_DELETE_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_DELETE, mutex_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_MUTEX_GET, mutex_ptr, mutex_ptr -> tx_mutex_owner, mutex_ptr -> tx_mutex_ownership_count); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_INFO_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_INFO_GET, mutex_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_PRIORITIZE_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_PRIORITIZE, mutex_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_PUT_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(TX_EL_MUTEX_PUT, mutex_ptr, mutex_ptr -> tx_mutex_owner, mutex_ptr -> tx_mutex_ownership_count); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(TX_EL_MUTEX_PERFORMANCE_INFO_GET, mutex_ptr); TX_EL_END_FILTER
|
||||
#define TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT TX_EL_NO_MUTEX_EVENTS TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET); TX_EL_END_FILTER
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define Event Log function prototypes. */
|
||||
|
||||
VOID _tx_el_initialize(VOID);
|
||||
UINT _tx_el_thread_register(TX_THREAD *thread_ptr);
|
||||
UINT _tx_el_thread_unregister(TX_THREAD *thread_ptr);
|
||||
VOID _tx_el_user_event_insert(UINT sub_type, ULONG info_1, ULONG info_2,
|
||||
ULONG info_3, ULONG info_4);
|
||||
VOID _tx_el_thread_running(TX_THREAD *thread_ptr);
|
||||
VOID _tx_el_thread_preempted(TX_THREAD *thread_ptr);
|
||||
VOID _tx_el_interrupt(UINT interrupt_number);
|
||||
VOID _tx_el_interrupt_end(UINT interrupt_number);
|
||||
VOID _tx_el_interrupt_control_call(void);
|
||||
VOID _tx_el_event_log_on(void);
|
||||
VOID _tx_el_event_log_off(void);
|
||||
VOID _tx_el_event_filter_set(UINT filter);
|
||||
|
||||
|
||||
/* Define macros that are used inside the ThreadX source code.
|
||||
If event logging is disabled, these macros will be defined
|
||||
as white space. */
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
#ifndef TX_NO_EVENT_INFO
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(a, b, c, d, e) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
|
||||
(ULONG) b;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =\
|
||||
(ULONG) c;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =\
|
||||
(ULONG) d;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =\
|
||||
(ULONG) e;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(a, b, c, d) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
|
||||
(ULONG) b;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =\
|
||||
(ULONG) c;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =\
|
||||
(ULONG) d;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(a, b, c) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
|
||||
(ULONG) b;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =\
|
||||
(ULONG) c;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(a, b) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =\
|
||||
(ULONG) b;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(a) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
TX_EL_NO_STATUS_EVENTS \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREAD_STATUS_CHANGE; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) b; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) a;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
TX_EL_END_FILTER \
|
||||
}
|
||||
#define TX_EL_THREAD_REGISTER(a) \
|
||||
_tx_el_thread_register(a);
|
||||
#define TX_EL_THREAD_UNREGISTER(a) \
|
||||
_tx_el_thread_unregister(a);
|
||||
#define TX_EL_INITIALIZE _tx_el_initialize();
|
||||
#else
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(a, b, c, d, e) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(a, b, c, d) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(a, b, c) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(a, b) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(a) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREADX_CALL; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) a; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) _tx_thread_current_ptr;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
}
|
||||
#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b) \
|
||||
{ \
|
||||
UCHAR *entry_ptr; \
|
||||
ULONG upper_tbu; \
|
||||
TX_EL_NO_STATUS_EVENTS \
|
||||
entry_ptr = *_tx_el_current_event; \
|
||||
*((unsigned short *) entry_ptr) = TX_EL_THREAD_STATUS_CHANGE; \
|
||||
*((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) = (unsigned short) b; \
|
||||
do { \
|
||||
upper_tbu = read_tbu(); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) = upper_tbu; \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =\
|
||||
(ULONG) read_tbl();\
|
||||
} while (upper_tbu != read_tbu()); \
|
||||
*((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =\
|
||||
(ULONG) a;\
|
||||
entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;\
|
||||
if (entry_ptr >= _tx_el_event_area_end) \
|
||||
{\
|
||||
entry_ptr = _tx_el_event_area_start;\
|
||||
}\
|
||||
*_tx_el_current_event = entry_ptr;\
|
||||
TX_EL_END_FILTER \
|
||||
}
|
||||
#define TX_EL_THREAD_REGISTER(a) \
|
||||
_tx_el_thread_register(a);
|
||||
#define TX_EL_THREAD_UNREGISTER(a) \
|
||||
_tx_el_thread_unregister(a);
|
||||
#define TX_EL_INITIALIZE _tx_el_initialize();
|
||||
#endif
|
||||
#else
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO4(a, b, c, d, e)
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO3(a, b, c, d)
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(a, b, c)
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO1(a, b)
|
||||
#define TX_EL_KERNEL_CALL_EVENT_INSERT_INFO0(a)
|
||||
#define TX_EL_THREAD_STATUS_CHANGE_INSERT(a, b)
|
||||
#define TX_EL_THREAD_REGISTER(a)
|
||||
#define TX_EL_THREAD_UNREGISTER(a)
|
||||
#define TX_EL_INITIALIZE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
77
ports_arch/ARMv7-M/threadx/ghs/inc/tx_ghs.h
Normal file
77
ports_arch/ARMv7-M/threadx/ghs/inc/tx_ghs.h
Normal 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_ */
|
406
ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h
Normal file
406
ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h
Normal 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
|
233
ports_arch/ARMv7-M/threadx/ghs/readme_threadx.txt
Normal file
233
ports_arch/ARMv7-M/threadx/ghs/readme_threadx.txt
Normal 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
|
||||
|
1165
ports_arch/ARMv7-M/threadx/ghs/src/tx_el.c
Normal file
1165
ports_arch/ARMv7-M/threadx/ghs/src/tx_el.c
Normal file
File diff suppressed because it is too large
Load Diff
485
ports_arch/ARMv7-M/threadx/ghs/src/tx_ghs.c
Normal file
485
ports_arch/ARMv7-M/threadx/ghs/src/tx_ghs.c
Normal 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 */
|
49
ports_arch/ARMv7-M/threadx/ghs/src/tx_ghse.c
Normal file
49
ports_arch/ARMv7-M/threadx/ghs/src/tx_ghse.c
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
291
ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_schedule.arm
Normal file
291
ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_schedule.arm
Normal 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
|
133
ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_stack_build.arm
Normal file
133
ports_arch/ARMv7-M/threadx/ghs/src/tx_thread_stack_build.arm
Normal 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
|
@ -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
|
241
ports_arch/ARMv7-M/threadx/ghs/src/tx_timer_interrupt.arm
Normal file
241
ports_arch/ARMv7-M/threadx/ghs/src/tx_timer_interrupt.arm
Normal 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
|
84
ports_arch/ARMv7-M/threadx/ghs/src/txr_ghs.c
Normal file
84
ports_arch/ARMv7-M/threadx/ghs/src/txr_ghs.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
18
ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt
Normal file
18
ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
230
ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx.bat
Normal file
230
ports_arch/ARMv7-M/threadx/gnu/example_build/build_threadx.bat
Normal file
@ -0,0 +1,230 @@
|
||||
del tx.a
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_stack_build.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_schedule.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_system_return.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_context_save.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_context_restore.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_interrupt_control.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_interrupt_disable.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_thread_interrupt_restore.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb ../src/tx_timer_interrupt.S
|
||||
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_allocate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_cleanup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_pool_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_block_release.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_allocate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_cleanup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_pool_search.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_byte_release.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_cleanup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_set.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_event_flags_set_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_high_level.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_kernel_enter.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_initialize_kernel_setup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_cleanup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_priority_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_mutex_put.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_cleanup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_flush.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_front_send.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_receive.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_send.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_queue_send_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_ceiling_put.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_cleanup.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_put.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_semaphore_put_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_entry_exit_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_identify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_preemption_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_priority_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_relinquish.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_reset.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_resume.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_shell_entry.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_sleep.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_analyze.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_error_handler.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_stack_error_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_suspend.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_preempt_check.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_resume.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_system_suspend.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_terminate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_time_slice.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_time_slice_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_timeout.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_thread_wait_abort.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_time_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_time_set.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_activate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_deactivate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_expiration_process.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_performance_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_performance_system_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_system_activate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_system_deactivate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_timer_thread_entry.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_buffer_full_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_enable.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_event_filter.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_event_unfilter.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_disable.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_initialize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_interrupt_control.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_isr_enter_insert.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_isr_exit_insert.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_object_register.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_object_unregister.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/tx_trace_user_event_insert.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_allocate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_pool_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_block_release.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_allocate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_pool_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_byte_release.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_set.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_event_flags_set_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_mutex_put.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_flush.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_front_send.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_receive.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_send.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_queue_send_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_ceiling_put.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_prioritize.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_put.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_semaphore_put_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_entry_exit_notify.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_info_get.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_preemption_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_priority_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_relinquish.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_reset.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_resume.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_suspend.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_terminate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_time_slice_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_thread_wait_abort.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_activate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_change.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_create.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_deactivate.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_delete.c
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc ../../../../common/src/txe_timer_info_get.c
|
||||
|
||||
arm-none-eabi-ar -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o
|
||||
arm-none-eabi-ar -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o
|
||||
arm-none-eabi-ar -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o
|
||||
arm-none-eabi-ar -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o
|
||||
arm-none-eabi-ar -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o
|
||||
arm-none-eabi-ar -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o
|
||||
arm-none-eabi-ar -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o
|
||||
arm-none-eabi-ar -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o
|
||||
arm-none-eabi-ar -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o
|
||||
arm-none-eabi-ar -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o
|
||||
arm-none-eabi-ar -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o
|
||||
arm-none-eabi-ar -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o
|
||||
arm-none-eabi-ar -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o
|
||||
arm-none-eabi-ar -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o
|
||||
arm-none-eabi-ar -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o
|
||||
arm-none-eabi-ar -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o
|
||||
arm-none-eabi-ar -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o
|
||||
arm-none-eabi-ar -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o
|
||||
arm-none-eabi-ar -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o
|
||||
arm-none-eabi-ar -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o
|
||||
arm-none-eabi-ar -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o
|
||||
arm-none-eabi-ar -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o
|
||||
arm-none-eabi-ar -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o
|
||||
arm-none-eabi-ar -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o
|
||||
arm-none-eabi-ar -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o
|
||||
arm-none-eabi-ar -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o
|
||||
arm-none-eabi-ar -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o
|
||||
arm-none-eabi-ar -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o
|
@ -0,0 +1,5 @@
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb cortexm4_vectors.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb cortexm4_crt0.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb tx_initialize_low_level.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -I../../../../common/inc -I../../inc sample_threadx.c
|
||||
arm-none-eabi-gcc -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -mthumb -T sample_threadx.ld -ereset_handler -nostartfiles -o sample_threadx.out -Wl,-Map=sample_threadx.map cortexm4_vectors.o cortexm4_crt0.o tx_initialize_low_level.o sample_threadx.o tx.a
|
91
ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_crt0.S
Normal file
91
ports_arch/ARMv7-M/threadx/gnu/example_build/cortexm4_crt0.S
Normal file
@ -0,0 +1,91 @@
|
||||
.syntax unified
|
||||
.section .init, "ax"
|
||||
.code 16
|
||||
.align 2
|
||||
.thumb_func
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
CPSID i
|
||||
ldr r1, =__stack_end__
|
||||
mov sp, r1
|
||||
|
||||
/* Copy initialised sections into RAM if required. */
|
||||
ldr r0, =__data_load_start__
|
||||
ldr r1, =__data_start__
|
||||
ldr r2, =__data_end__
|
||||
bl crt0_memory_copy
|
||||
|
||||
/* Zero bss. */
|
||||
ldr r0, =__bss_start__
|
||||
ldr r1, =__bss_end__
|
||||
mov r2, #0
|
||||
bl crt0_memory_set
|
||||
|
||||
/* Setup heap - not recommended for Threadx but here for compatibility reasons */
|
||||
ldr r0, = __heap_start__
|
||||
ldr r1, = __heap_end__
|
||||
sub r1, r1, r0
|
||||
mov r2, #0
|
||||
str r2, [r0]
|
||||
add r0, r0, #4
|
||||
str r1, [r0]
|
||||
|
||||
/* constructors in case of using C++ */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
crt0_ctor_loop:
|
||||
cmp r0, r1
|
||||
beq crt0_ctor_end
|
||||
ldr r2, [r0]
|
||||
add r0, #4
|
||||
push {r0-r1}
|
||||
blx r2
|
||||
pop {r0-r1}
|
||||
b crt0_ctor_loop
|
||||
crt0_ctor_end:
|
||||
|
||||
/* Setup call frame for main() */
|
||||
mov r0, #0
|
||||
mov lr, r0
|
||||
mov r12, sp
|
||||
|
||||
start:
|
||||
/* Jump to main() */
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
ldr r2, =main
|
||||
blx r2
|
||||
/* when main returns, loop forever. */
|
||||
crt0_exit_loop:
|
||||
b crt0_exit_loop
|
||||
|
||||
/* Startup helper functions. */
|
||||
|
||||
crt0_memory_copy:
|
||||
cmp r0, r1
|
||||
beq memory_copy_done
|
||||
memory_copy_loop:
|
||||
ldrb r3, [r0]
|
||||
add r0, r0, #1
|
||||
strb r3, [r1]
|
||||
add r1, r1, #1
|
||||
cmp r1, r2
|
||||
bne memory_copy_loop
|
||||
memory_copy_done:
|
||||
bx lr
|
||||
|
||||
crt0_memory_set:
|
||||
cmp r0, r1
|
||||
beq memory_set_done
|
||||
strb r2, [r0]
|
||||
add r0, r0, #1
|
||||
b crt0_memory_set
|
||||
memory_set_done:
|
||||
bx lr
|
||||
|
||||
/* Setup attibutes of stack and heap sections so they don't take up room in the elf file */
|
||||
.section .stack, "wa", %nobits
|
||||
.section .stack_process, "wa", %nobits
|
||||
.section .heap, "wa", %nobits
|
||||
|
@ -0,0 +1,77 @@
|
||||
.global reset_handler
|
||||
|
||||
.global __tx_NMIHandler
|
||||
.global __tx_BadHandler
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_DBGHandler
|
||||
.global PendSV_Handler
|
||||
.global __tx_SysTickHandler
|
||||
.global __tx_BadHandler
|
||||
|
||||
.syntax unified
|
||||
.section .vectors, "ax"
|
||||
.code 16
|
||||
.align 0
|
||||
.global _vectors
|
||||
|
||||
_vectors:
|
||||
.word __stack_end__
|
||||
.word reset_handler
|
||||
.word __tx_NMIHandler
|
||||
.word __tx_HardfaultHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
|
||||
.word __tx_DBGHandler
|
||||
.word 0 // Reserved
|
||||
.word PendSV_Handler
|
||||
.word __tx_SysTickHandler // Used by Threadx timer functionality
|
||||
.word __tx_BadHandler // Populate with user Interrupt handler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
|
||||
.section .init, "ax"
|
||||
.thumb_func
|
||||
reset_handler:
|
||||
// low level hardware config, such as PLL setup goes here
|
||||
b _start
|
||||
|
||||
|
||||
|
370
ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.c
Normal file
370
ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.c
Normal 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;
|
||||
}
|
||||
}
|
125
ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.ld
Normal file
125
ports_arch/ARMv7-M/threadx/gnu/example_build/sample_threadx.ld
Normal file
@ -0,0 +1,125 @@
|
||||
MEMORY
|
||||
{
|
||||
RAM (wx) : ORIGIN = 0x20000000, LENGTH = 0x00800000
|
||||
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00400000
|
||||
}
|
||||
|
||||
__STACKSIZE__ = 1024;
|
||||
__STACKSIZE_PROCESS__ = 0;
|
||||
__HEAPSIZE__ = 128;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.vectors :
|
||||
{
|
||||
KEEP(*(.vectors .vectors.*))
|
||||
} > FLASH
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text*)
|
||||
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
__ctors_start__ = ALIGN(4);
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
__ctors_end__ = ALIGN(4);
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
__dtors_start__ = ALIGN(4);
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
__dtors_end__ = ALIGN(4);
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
KEEP(*(.eh_frame*))
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
__data_load_start__ = ALIGN (4);
|
||||
|
||||
.data : AT (__data_load_start__)
|
||||
{
|
||||
__data_start__ = .;
|
||||
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
KEEP(*(.jcr*))
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
|
||||
__data_end__ = .;
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__heap_start__ = ALIGN(4);
|
||||
*(.heap)
|
||||
. = ALIGN(. + __HEAPSIZE__, 4);
|
||||
__heap_end__ = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
.stack ALIGN(4) (NOLOAD) :
|
||||
{
|
||||
__stack_start__ = ALIGN(4);
|
||||
*(.stack)
|
||||
. = ALIGN(. + __STACKSIZE__, 4);
|
||||
__stack_end__ = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
__RAM_segment_used_end__ = .;
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_initialize_unused_memory
|
||||
.global __RAM_segment_used_end__
|
||||
.global _tx_timer_interrupt
|
||||
.global __main
|
||||
.global _vectors
|
||||
.global __tx_NMIHandler // NMI
|
||||
.global __tx_BadHandler // HardFault
|
||||
.global __tx_SVCallHandler // SVCall
|
||||
.global __tx_DBGHandler // Monitor
|
||||
.global __tx_PendSVHandler // PendSV
|
||||
.global __tx_SysTickHandler // SysTick
|
||||
.global __tx_IntHandler // Int 0
|
||||
|
||||
SYSTEM_CLOCK = 6000000
|
||||
SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Cortex-Mx/GNU */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), added */
|
||||
/* TX_NO_TIMER support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_initialize_low_level(VOID)
|
||||
// {
|
||||
.global _tx_initialize_low_level
|
||||
.thumb_func
|
||||
_tx_initialize_low_level:
|
||||
|
||||
/* Ensure that interrupts are disabled. */
|
||||
CPSID i
|
||||
|
||||
/* Set base of available memory to end of non-initialised RAM area. */
|
||||
LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer
|
||||
LDR r1, =__RAM_segment_used_end__ // Build first free address
|
||||
ADD r1, r1, #4 //
|
||||
STR r1, [r0] // Setup first unused memory pointer
|
||||
|
||||
/* Setup Vector Table Offset Register. */
|
||||
MOV r0, #0xE000E000 // Build address of NVIC registers
|
||||
LDR r1, =_vectors // Pickup address of vector table
|
||||
STR r1, [r0, #0xD08] // Set vector table address
|
||||
|
||||
/* Set system stack pointer from vector value. */
|
||||
LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
|
||||
LDR r1, =_vectors // Pickup address of vector table
|
||||
LDR r1, [r1] // Pickup reset stack pointer
|
||||
STR r1, [r0] // Save system stack pointer
|
||||
|
||||
#ifndef TX_NO_TIMER
|
||||
/* Configure SysTick. */
|
||||
MOV r0, #0xE000E000 // Build address of NVIC registers
|
||||
LDR r1, =SYSTICK_CYCLES
|
||||
STR r1, [r0, #0x14] // Setup SysTick Reload Value
|
||||
MOV r1, #0x7 // Build SysTick Control Enable Value
|
||||
STR r1, [r0, #0x10] // Setup SysTick Control
|
||||
#endif
|
||||
|
||||
/* Configure handler priorities. */
|
||||
LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
|
||||
STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
|
||||
LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
|
||||
STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
|
||||
// Note: SVC must be lowest priority, which is 0xFF
|
||||
LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
|
||||
STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
|
||||
// Note: PnSV must be lowest priority, which is 0xFF
|
||||
|
||||
/* Return to caller. */
|
||||
BX lr
|
||||
// }
|
||||
|
||||
/* Define shells for each of the unused vectors. */
|
||||
.global __tx_BadHandler
|
||||
.thumb_func
|
||||
__tx_BadHandler:
|
||||
B __tx_BadHandler
|
||||
|
||||
/* added to catch the hardfault */
|
||||
.global __tx_HardfaultHandler
|
||||
.thumb_func
|
||||
__tx_HardfaultHandler:
|
||||
B __tx_HardfaultHandler
|
||||
|
||||
/* added to catch the SVC */
|
||||
.global __tx_SVCallHandler
|
||||
.thumb_func
|
||||
__tx_SVCallHandler:
|
||||
B __tx_SVCallHandler
|
||||
|
||||
/* Generic interrupt handler template */
|
||||
.global __tx_IntHandler
|
||||
.thumb_func
|
||||
__tx_IntHandler:
|
||||
// VOID InterruptHandler (VOID)
|
||||
// {
|
||||
PUSH {r0, lr}
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
#endif
|
||||
/* Do interrupt handler work here */
|
||||
/* BL <your C Function>.... */
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
BL _tx_execution_isr_exit // Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX lr
|
||||
// }
|
||||
|
||||
#ifndef TX_NO_TIMER
|
||||
/* System Tick timer interrupt handler */
|
||||
.global __tx_SysTickHandler
|
||||
.global SysTick_Handler
|
||||
.thumb_func
|
||||
__tx_SysTickHandler:
|
||||
.thumb_func
|
||||
SysTick_Handler:
|
||||
// VOID SysTick_Handler (VOID)
|
||||
// {
|
||||
PUSH {r0, lr}
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
#endif
|
||||
BL _tx_timer_interrupt
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
BL _tx_execution_isr_exit // Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX lr
|
||||
// }
|
||||
#endif
|
||||
|
||||
/* NMI, DBG handlers */
|
||||
.global __tx_NMIHandler
|
||||
.thumb_func
|
||||
__tx_NMIHandler:
|
||||
B __tx_NMIHandler
|
||||
|
||||
.global __tx_DBGHandler
|
||||
.thumb_func
|
||||
__tx_DBGHandler:
|
||||
B __tx_DBGHandler
|
209
ports_arch/ARMv7-M/threadx/gnu/readme_threadx.txt
Normal file
209
ports_arch/ARMv7-M/threadx/gnu/readme_threadx.txt
Normal file
@ -0,0 +1,209 @@
|
||||
Microsoft's Azure RTOS ThreadX for ARMv7-M
|
||||
(Cortex-M3, Cortex-M4, Cortex-M7)
|
||||
Using the GNU Tools
|
||||
|
||||
|
||||
1. Building the ThreadX run-time Library
|
||||
|
||||
Navigate to the "example_build" directory. Ensure that
|
||||
you have setup your path and other environment variables necessary for the ARM
|
||||
GNU compiler. At this point you may run the build_threadx.bat batch file.
|
||||
This will build the ThreadX run-time environment in the "example_build"
|
||||
directory.
|
||||
|
||||
You should observe assembly and compilation of a series of ThreadX source
|
||||
files. At the end of the batch file, they are all combined into the
|
||||
run-time library file: tx.a. This file must be linked with your
|
||||
application in order to use ThreadX.
|
||||
|
||||
|
||||
2. Demonstration System
|
||||
|
||||
The ThreadX demonstration is designed to execute on Cortex-M evaluation boards
|
||||
or on a dedicated simulator.
|
||||
|
||||
Building the demonstration is easy, simply execute the build_threadx_sample.bat
|
||||
batch file while inside the "example_build" directory.
|
||||
|
||||
You should observe the compilation of sample_threadx.c (which is the demonstration
|
||||
application) and linking with tx.a. The resulting file sample_threadx.out is a binary
|
||||
file that can be downloaded and executed on the a simulator, or downloaded to a board.
|
||||
|
||||
|
||||
3. System Initialization
|
||||
|
||||
The entry point in ThreadX for the Cortex-M using gnu tools uses the standard GNU
|
||||
Cortex-M reset sequence. From the reset vector the C runtime will be initialized.
|
||||
|
||||
The ThreadX tx_initialize_low_level.S file is responsible for setting up
|
||||
various system data structures, the vector area, and a periodic timer interrupt
|
||||
source.
|
||||
|
||||
In addition, _tx_initialize_low_level determines the first available
|
||||
address for use by the application, which is supplied as the sole input
|
||||
parameter to your application definition function, tx_application_define.
|
||||
|
||||
|
||||
4. Register Usage and Stack Frames
|
||||
|
||||
The following defines the saved context stack frames for context switches
|
||||
that occur as a result of interrupt handling or from thread-level API calls.
|
||||
All suspended threads have the same stack frame in the Cortex-M version of
|
||||
ThreadX. The top of the suspended thread's stack is pointed to by
|
||||
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
|
||||
|
||||
Non-FPU Stack Frame:
|
||||
|
||||
Stack Offset Stack Contents
|
||||
|
||||
0x00 lr Interrupted lr (lr at time of PENDSV)
|
||||
0x04 r4 Software stacked GP registers
|
||||
0x08 r5
|
||||
0x0C r6
|
||||
0x10 r7
|
||||
0x14 r8
|
||||
0x18 r9
|
||||
0x1C r10
|
||||
0x20 r11
|
||||
0x24 r0 Hardware stacked registers
|
||||
0x28 r1
|
||||
0x2C r2
|
||||
0x30 r3
|
||||
0x34 r12
|
||||
0x38 lr
|
||||
0x3C pc
|
||||
0x40 xPSR
|
||||
|
||||
FPU Stack Frame (only interrupted thread with FPU enabled):
|
||||
|
||||
Stack Offset Stack Contents
|
||||
|
||||
0x00 lr Interrupted lr (lr at time of PENDSV)
|
||||
0x04 s16 Software stacked FPU registers
|
||||
0x08 s17
|
||||
0x0C s18
|
||||
0x10 s19
|
||||
0x14 s20
|
||||
0x18 s21
|
||||
0x1C s22
|
||||
0x20 s23
|
||||
0x24 s24
|
||||
0x28 s25
|
||||
0x2C s26
|
||||
0x30 s27
|
||||
0x34 s28
|
||||
0x38 s29
|
||||
0x3C s30
|
||||
0x40 s31
|
||||
0x44 r4 Software stacked registers
|
||||
0x48 r5
|
||||
0x4C r6
|
||||
0x50 r7
|
||||
0x54 r8
|
||||
0x58 r9
|
||||
0x5C r10
|
||||
0x60 r11
|
||||
0x64 r0 Hardware stacked registers
|
||||
0x68 r1
|
||||
0x6C r2
|
||||
0x70 r3
|
||||
0x74 r12
|
||||
0x78 lr
|
||||
0x7C pc
|
||||
0x80 xPSR
|
||||
0x84 s0 Hardware stacked FPU registers
|
||||
0x88 s1
|
||||
0x8C s2
|
||||
0x90 s3
|
||||
0x94 s4
|
||||
0x98 s5
|
||||
0x9C s6
|
||||
0xA0 s7
|
||||
0xA4 s8
|
||||
0xA8 s9
|
||||
0xAC s10
|
||||
0xB0 s11
|
||||
0xB4 s12
|
||||
0xB8 s13
|
||||
0xBC s14
|
||||
0xC0 s15
|
||||
0xC4 fpscr
|
||||
|
||||
|
||||
5. Improving Performance
|
||||
|
||||
The distribution version of ThreadX is built without any compiler optimizations.
|
||||
This makes it easy to debug because you can trace or set breakpoints inside of
|
||||
ThreadX itself. Of course, this costs some performance. To make it run faster,
|
||||
you can change the build_threadx.bat file to remove the -g option and enable
|
||||
all compiler optimizations.
|
||||
|
||||
In addition, you can eliminate the ThreadX basic API error checking by
|
||||
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
|
||||
defined.
|
||||
|
||||
|
||||
6. Interrupt Handling
|
||||
|
||||
ThreadX provides complete and high-performance interrupt handling for Cortex-M
|
||||
targets. There are a certain set of requirements that are defined in the
|
||||
following sub-sections:
|
||||
|
||||
|
||||
6.1 Vector Area
|
||||
|
||||
The Cortex-M vectors start at the label __tx_vectors or similar. The application may modify
|
||||
the vector area according to its needs. There is code in tx_initialize_low_level() that will
|
||||
configure the vector base register.
|
||||
|
||||
|
||||
6.2 Managed Interrupts
|
||||
|
||||
A ThreadX managed interrupt is defined below. By following these conventions, the
|
||||
application ISR is then allowed access to various ThreadX services from the ISR.
|
||||
Here is the standard template for managed ISRs in ThreadX:
|
||||
|
||||
|
||||
.global __tx_IntHandler
|
||||
.thumb_func
|
||||
__tx_IntHandler:
|
||||
; VOID InterruptHandler (VOID)
|
||||
; {
|
||||
PUSH {r0, lr}
|
||||
|
||||
; /* Do interrupt handler work here */
|
||||
; /* BL <your interrupt routine in C> */
|
||||
|
||||
POP {r0, lr}
|
||||
BX lr
|
||||
; }
|
||||
|
||||
|
||||
Note: the Cortex-M requires exception handlers to be thumb labels, this implies bit 0 set.
|
||||
To accomplish this, the declaration of the label has to be preceded by the assembler directive
|
||||
.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
|
||||
be inserted in the correct location in the interrupt vector table. This table is typically
|
||||
located in either your runtime startup file or in the tx_initialize_low_level.S file.
|
||||
|
||||
|
||||
7. FPU Support
|
||||
|
||||
ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
|
||||
can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
|
||||
context - no additional setup by the application.
|
||||
|
||||
|
||||
8. Revision History
|
||||
|
||||
For generic code revision information, please refer to the readme_threadx_generic.txt
|
||||
file, which is included in your distribution. The following details the revision
|
||||
information associated with this specific port of ThreadX:
|
||||
|
||||
06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using GNU tools.
|
||||
|
||||
|
||||
Copyright(c) 1996-2021 Microsoft Corporation
|
||||
|
||||
|
||||
https://azure.com/rtos
|
||||
|
723
ports_arch/ARMv7-M/threadx/gnu/src/tx_misra.S
Normal file
723
ports_arch/ARMv7-M/threadx/gnu/src/tx_misra.S
Normal file
@ -0,0 +1,723 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** ThreadX MISRA Compliance */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
#define SHT_PROGBITS 0x1
|
||||
|
||||
.global __aeabi_memset
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_thread_interrupt_disable
|
||||
.global _tx_thread_interrupt_restore
|
||||
.global _tx_thread_stack_analyze
|
||||
.global _tx_thread_stack_error_handler
|
||||
.global _tx_thread_system_state
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_trace_buffer_current_ptr
|
||||
.global _tx_trace_buffer_end_ptr
|
||||
.global _tx_trace_buffer_start_ptr
|
||||
.global _tx_trace_event_enable_bits
|
||||
.global _tx_trace_full_notify_function
|
||||
.global _tx_trace_header_ptr
|
||||
#endif
|
||||
|
||||
.global _tx_misra_always_true
|
||||
.global _tx_misra_block_pool_to_uchar_pointer_convert
|
||||
.global _tx_misra_byte_pool_to_uchar_pointer_convert
|
||||
.global _tx_misra_char_to_uchar_pointer_convert
|
||||
.global _tx_misra_const_char_to_char_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_entry_to_uchar_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_indirect_void_to_uchar_pointer_convert
|
||||
.global _tx_misra_memset
|
||||
.global _tx_misra_message_copy
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_object_to_uchar_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_pointer_to_ulong_convert
|
||||
.global _tx_misra_status_get
|
||||
.global _tx_misra_thread_stack_check
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_time_stamp_get
|
||||
#endif
|
||||
.global _tx_misra_timer_indirect_to_void_pointer_convert
|
||||
.global _tx_misra_timer_pointer_add
|
||||
.global _tx_misra_timer_pointer_dif
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_trace_event_insert
|
||||
#endif
|
||||
.global _tx_misra_uchar_pointer_add
|
||||
.global _tx_misra_uchar_pointer_dif
|
||||
.global _tx_misra_uchar_pointer_sub
|
||||
.global _tx_misra_uchar_to_align_type_pointer_convert
|
||||
.global _tx_misra_uchar_to_block_pool_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_uchar_to_entry_pointer_convert
|
||||
.global _tx_misra_uchar_to_header_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
|
||||
.global _tx_misra_uchar_to_indirect_uchar_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
.global _tx_misra_uchar_to_object_pointer_convert
|
||||
#endif
|
||||
.global _tx_misra_uchar_to_void_pointer_convert
|
||||
.global _tx_misra_ulong_pointer_add
|
||||
.global _tx_misra_ulong_pointer_dif
|
||||
.global _tx_misra_ulong_pointer_sub
|
||||
.global _tx_misra_ulong_to_pointer_convert
|
||||
.global _tx_misra_ulong_to_thread_pointer_convert
|
||||
.global _tx_misra_user_timer_pointer_get
|
||||
.global _tx_misra_void_to_block_pool_pointer_convert
|
||||
.global _tx_misra_void_to_byte_pool_pointer_convert
|
||||
.global _tx_misra_void_to_event_flags_pointer_convert
|
||||
.global _tx_misra_void_to_indirect_uchar_pointer_convert
|
||||
.global _tx_misra_void_to_mutex_pointer_convert
|
||||
.global _tx_misra_void_to_queue_pointer_convert
|
||||
.global _tx_misra_void_to_semaphore_pointer_convert
|
||||
.global _tx_misra_void_to_thread_pointer_convert
|
||||
.global _tx_misra_void_to_uchar_pointer_convert
|
||||
.global _tx_misra_void_to_ulong_pointer_convert
|
||||
.global _tx_misra_ipsr_get
|
||||
.global _tx_misra_control_get
|
||||
.global _tx_misra_control_set
|
||||
#ifdef __ARM_FP
|
||||
.global _tx_misra_fpccr_get
|
||||
.global _tx_misra_vfp_touch
|
||||
#endif
|
||||
|
||||
.global _tx_misra_event_flags_group_not_used
|
||||
.global _tx_misra_event_flags_set_notify_not_used
|
||||
.global _tx_misra_queue_not_used
|
||||
.global _tx_misra_queue_send_notify_not_used
|
||||
.global _tx_misra_semaphore_not_used
|
||||
.global _tx_misra_semaphore_put_notify_not_used
|
||||
.global _tx_misra_thread_entry_exit_notify_not_used
|
||||
.global _tx_misra_thread_not_used
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
.thumb_func
|
||||
_tx_misra_memset:
|
||||
PUSH {R4,LR}
|
||||
MOVS R4,R0
|
||||
MOVS R0,R2
|
||||
MOVS R2,R1
|
||||
MOVS R1,R0
|
||||
MOVS R0,R4
|
||||
BL __aeabi_memset
|
||||
POP {R4,PC} // return
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_uchar_pointer_add:
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_uchar_pointer_sub:
|
||||
RSBS R1,R1,#+0
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_uchar_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
/** */
|
||||
/** This single function serves all of the below prototypes. */
|
||||
/** */
|
||||
/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
|
||||
/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
|
||||
/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
|
||||
/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
|
||||
/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
|
||||
/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
|
||||
/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
|
||||
/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
|
||||
/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
|
||||
/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
|
||||
/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
|
||||
/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
|
||||
/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
|
||||
/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
|
||||
/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
|
||||
/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
|
||||
/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
|
||||
/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
|
||||
/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
|
||||
/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
|
||||
/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
|
||||
/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
|
||||
/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
|
||||
/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
|
||||
/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
|
||||
/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
|
||||
/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
|
||||
/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
|
||||
/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
|
||||
/** */
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_pointer_to_ulong_convert:
|
||||
_tx_misra_ulong_to_pointer_convert:
|
||||
_tx_misra_indirect_void_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_indirect_uchar_pointer_convert:
|
||||
_tx_misra_block_pool_to_uchar_pointer_convert:
|
||||
_tx_misra_void_to_block_pool_pointer_convert:
|
||||
_tx_misra_void_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_block_pool_pointer_convert:
|
||||
_tx_misra_void_to_indirect_uchar_pointer_convert:
|
||||
_tx_misra_void_to_byte_pool_pointer_convert:
|
||||
_tx_misra_byte_pool_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_align_type_pointer_convert:
|
||||
_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
|
||||
_tx_misra_void_to_event_flags_pointer_convert:
|
||||
_tx_misra_void_to_ulong_pointer_convert:
|
||||
_tx_misra_void_to_mutex_pointer_convert:
|
||||
_tx_misra_void_to_queue_pointer_convert:
|
||||
_tx_misra_void_to_semaphore_pointer_convert:
|
||||
_tx_misra_uchar_to_void_pointer_convert:
|
||||
_tx_misra_ulong_to_thread_pointer_convert:
|
||||
_tx_misra_timer_indirect_to_void_pointer_convert:
|
||||
_tx_misra_const_char_to_char_pointer_convert:
|
||||
_tx_misra_void_to_thread_pointer_convert:
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
_tx_misra_object_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_object_pointer_convert:
|
||||
_tx_misra_uchar_to_header_pointer_convert:
|
||||
_tx_misra_uchar_to_entry_pointer_convert:
|
||||
_tx_misra_entry_to_uchar_pointer_convert:
|
||||
#endif
|
||||
_tx_misra_char_to_uchar_pointer_convert:
|
||||
_tx_misra_event_flags_group_not_used:
|
||||
_tx_misra_event_flags_set_notify_not_used:
|
||||
_tx_misra_queue_not_used:
|
||||
_tx_misra_queue_send_notify_not_used:
|
||||
_tx_misra_semaphore_not_used:
|
||||
_tx_misra_semaphore_put_notify_not_used:
|
||||
_tx_misra_thread_entry_exit_notify_not_used:
|
||||
_tx_misra_thread_not_used:
|
||||
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ulong_pointer_add:
|
||||
ADD R0,R0,R1, LSL #+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ulong_pointer_sub:
|
||||
MVNS R2,#+3
|
||||
MULS R1,R2,R1
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ulong_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
ASRS R0,R0,#+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
|
||||
/** UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_message_copy:
|
||||
PUSH {R4,R5}
|
||||
LDR R3,[R0, #+0]
|
||||
LDR R4,[R1, #+0]
|
||||
LDR R5,[R3, #+0]
|
||||
STR R5,[R4, #+0]
|
||||
ADDS R4,R4,#+4
|
||||
ADDS R3,R3,#+4
|
||||
CMP R2,#+2
|
||||
BCC.N _tx_misra_message_copy_0
|
||||
SUBS R2,R2,#+1
|
||||
B.N _tx_misra_message_copy_1
|
||||
_tx_misra_message_copy_2:
|
||||
LDR R5,[R3, #+0]
|
||||
STR R5,[R4, #+0]
|
||||
ADDS R4,R4,#+4
|
||||
ADDS R3,R3,#+4
|
||||
SUBS R2,R2,#+1
|
||||
_tx_misra_message_copy_1:
|
||||
CMP R2,#+0
|
||||
BNE.N _tx_misra_message_copy_2
|
||||
_tx_misra_message_copy_0:
|
||||
STR R3,[R0, #+0]
|
||||
STR R4,[R1, #+0]
|
||||
POP {R4,R5}
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
|
||||
/** TX_TIMER_INTERNAL **ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_timer_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
ASRS R0,R0,#+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
|
||||
/** **ptr1, ULONG size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_timer_pointer_add:
|
||||
ADD R0,R0,R1, LSL #+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
|
||||
/** *internal_timer, TX_TIMER **user_timer); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_user_timer_pointer_get:
|
||||
SUBS R0,#8
|
||||
STR R0,[R1, #+0]
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
|
||||
/** VOID **highest_stack); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_thread_stack_check:
|
||||
PUSH {R3-R5,LR}
|
||||
MOVS R4,R0
|
||||
MOVS R5,R1
|
||||
BL _tx_thread_interrupt_disable
|
||||
CMP R4,#+0
|
||||
BEQ.N _tx_misra_thread_stack_check_0
|
||||
LDR R1,[R4, #+0]
|
||||
LDR R2,=0x54485244
|
||||
CMP R1,R2
|
||||
BNE.N _tx_misra_thread_stack_check_0
|
||||
LDR R1,[R4, #+8]
|
||||
LDR R2,[R5, #+0]
|
||||
CMP R1,R2
|
||||
BCS.N _tx_misra_thread_stack_check_1
|
||||
LDR R1,[R4, #+8]
|
||||
STR R1,[R5, #+0]
|
||||
_tx_misra_thread_stack_check_1:
|
||||
LDR R1,[R4, #+12]
|
||||
LDR R1,[R1, #+0]
|
||||
CMP R1,#-269488145
|
||||
BNE.N _tx_misra_thread_stack_check_2
|
||||
LDR R1,[R4, #+16]
|
||||
LDR R1,[R1, #+1]
|
||||
CMP R1,#-269488145
|
||||
BNE.N _tx_misra_thread_stack_check_2
|
||||
LDR R1,[R5, #+0]
|
||||
LDR R2,[R4, #+12]
|
||||
CMP R1,R2
|
||||
BCS.N _tx_misra_thread_stack_check_3
|
||||
_tx_misra_thread_stack_check_2:
|
||||
BL _tx_thread_interrupt_restore
|
||||
MOVS R0,R4
|
||||
BL _tx_thread_stack_error_handler
|
||||
BL _tx_thread_interrupt_disable
|
||||
_tx_misra_thread_stack_check_3:
|
||||
LDR R1,[R5, #+0]
|
||||
LDR R1,[R1, #-4]
|
||||
CMP R1,#-269488145
|
||||
BEQ.N _tx_misra_thread_stack_check_0
|
||||
BL _tx_thread_interrupt_restore
|
||||
MOVS R0,R4
|
||||
BL _tx_thread_stack_analyze
|
||||
BL _tx_thread_interrupt_disable
|
||||
_tx_misra_thread_stack_check_0:
|
||||
BL _tx_thread_interrupt_restore
|
||||
POP {R0,R4,R5,PC} // return
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
|
||||
/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
|
||||
/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_trace_event_insert:
|
||||
PUSH {R3-R7,LR}
|
||||
LDR.N R4,DataTable2_1
|
||||
LDR R4,[R4, #+0]
|
||||
CMP R4,#+0
|
||||
BEQ.N _tx_misra_trace_event_insert_0
|
||||
LDR.N R5,DataTable2_2
|
||||
LDR R5,[R5, #+0]
|
||||
LDR R6,[SP, #+28]
|
||||
TST R5,R6
|
||||
BEQ.N _tx_misra_trace_event_insert_0
|
||||
LDR.N R5,DataTable2_3
|
||||
LDR R5,[R5, #+0]
|
||||
LDR.N R6,DataTable2_4
|
||||
LDR R6,[R6, #+0]
|
||||
CMP R5,#+0
|
||||
BNE.N _tx_misra_trace_event_insert_1
|
||||
LDR R5,[R6, #+44]
|
||||
LDR R7,[R6, #+60]
|
||||
LSLS R7,R7,#+16
|
||||
ORRS R7,R7,#0x80000000
|
||||
ORRS R5,R7,R5
|
||||
B.N _tx_misra_trace_event_insert_2
|
||||
_tx_misra_trace_event_insert_1:
|
||||
CMP R5,#-252645136
|
||||
BCS.N _tx_misra_trace_event_insert_3
|
||||
MOVS R5,R6
|
||||
MOVS R6,#-1
|
||||
B.N _tx_misra_trace_event_insert_2
|
||||
_tx_misra_trace_event_insert_3:
|
||||
MOVS R6,#-252645136
|
||||
MOVS R5,#+0
|
||||
_tx_misra_trace_event_insert_2:
|
||||
STR R6,[R4, #+0]
|
||||
STR R5,[R4, #+4]
|
||||
STR R0,[R4, #+8]
|
||||
LDR R0,[SP, #+32]
|
||||
STR R0,[R4, #+12]
|
||||
STR R1,[R4, #+16]
|
||||
STR R2,[R4, #+20]
|
||||
STR R3,[R4, #+24]
|
||||
LDR R0,[SP, #+24]
|
||||
STR R0,[R4, #+28]
|
||||
ADDS R4,R4,#+32
|
||||
LDR.N R0,DataTable2_5
|
||||
LDR R0,[R0, #+0]
|
||||
CMP R4,R0
|
||||
BCC.N _tx_misra_trace_event_insert_4
|
||||
LDR.N R0,DataTable2_6
|
||||
LDR R4,[R0, #+0]
|
||||
LDR.N R0,DataTable2_1
|
||||
STR R4,[R0, #+0]
|
||||
LDR.N R0,DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
STR R4,[R0, #+32]
|
||||
LDR.N R0,DataTable2_8
|
||||
LDR R0,[R0, #+0]
|
||||
CMP R0,#+0
|
||||
BEQ.N _tx_misra_trace_event_insert_0
|
||||
LDR.N R0,DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
LDR.N R1,DataTable2_8
|
||||
LDR R1,[R1, #+0]
|
||||
BLX R1
|
||||
B.N _tx_misra_trace_event_insert_0
|
||||
_tx_misra_trace_event_insert_4:
|
||||
LDR.N R0,DataTable2_1
|
||||
STR R4,[R0, #+0]
|
||||
LDR.N R0,DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
STR R4,[R0, #+32]
|
||||
_tx_misra_trace_event_insert_0:
|
||||
POP {R0,R4-R7,PC} // return
|
||||
|
||||
|
||||
.data
|
||||
DataTable2_1:
|
||||
.word _tx_trace_buffer_current_ptr
|
||||
|
||||
.data
|
||||
DataTable2_2:
|
||||
.word _tx_trace_event_enable_bits
|
||||
|
||||
.data
|
||||
DataTable2_5:
|
||||
.word _tx_trace_buffer_end_ptr
|
||||
|
||||
.data
|
||||
DataTable2_6:
|
||||
.word _tx_trace_buffer_start_ptr
|
||||
|
||||
.data
|
||||
DataTable2_7:
|
||||
.word _tx_trace_header_ptr
|
||||
|
||||
.data
|
||||
DataTable2_8:
|
||||
.word _tx_trace_full_notify_function
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_time_stamp_get(VOID); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_time_stamp_get:
|
||||
MOVS R0,#+0
|
||||
BX LR // return
|
||||
|
||||
#endif
|
||||
|
||||
.data
|
||||
DataTable2_3:
|
||||
.word _tx_thread_system_state
|
||||
|
||||
.data
|
||||
DataTable2_4:
|
||||
.word _tx_thread_current_ptr
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_always_true(void); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_always_true:
|
||||
MOVS R0,#+1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_status_get(UINT status); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_status_get:
|
||||
MOVS R0,#+0
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ipsr_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_ipsr_get:
|
||||
MRS R0, IPSR
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_control_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_control_get:
|
||||
MRS R0, CONTROL
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** void _tx_misra_control_set(ULONG value); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_control_set:
|
||||
MSR CONTROL, R0
|
||||
BX LR // return
|
||||
|
||||
|
||||
#ifdef __ARM_FP
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_fpccr_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_fpccr_get:
|
||||
LDR r0, =0xE000EF34 // Build FPCCR address
|
||||
LDR r0, [r0] // Load FPCCR value
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** void _tx_misra_vfp_touch(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_tx_misra_vfp_touch:
|
||||
vmov.f32 s0, s0
|
||||
BX LR // return
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
.data
|
||||
.word 0
|
@ -0,0 +1,88 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
.global _tx_execution_isr_exit
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is only needed for legacy applications and it should */
|
||||
/* not be called in any new development on a Cortex-M. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* [_tx_execution_isr_exit] Execution profiling ISR exit */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_restore(VOID)
|
||||
// {
|
||||
.global _tx_thread_context_restore
|
||||
.thumb_func
|
||||
_tx_thread_context_restore:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the ISR exit function to indicate an ISR is complete. */
|
||||
PUSH {r0, lr} // Save return address
|
||||
BL _tx_execution_isr_exit // Call the ISR exit function
|
||||
POP {r0, lr} // Recover return address
|
||||
#endif
|
||||
|
||||
BX lr
|
||||
// }
|
86
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_save.S
Normal file
86
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_context_save.S
Normal file
@ -0,0 +1,86 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is only needed for legacy applications and it should */
|
||||
/* not be called in any new development on a Cortex-M. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* [_tx_execution_isr_enter] Execution profiling ISR enter */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_save(VOID)
|
||||
// {
|
||||
.global _tx_thread_context_save
|
||||
.thumb_func
|
||||
_tx_thread_context_save:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the ISR enter function to indicate an ISR is starting. */
|
||||
PUSH {r0, lr} // Save return address
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {r0, lr} // Recover return address
|
||||
#endif
|
||||
|
||||
/* Context is already saved - just return. */
|
||||
|
||||
BX lr
|
||||
// }
|
@ -0,0 +1,85 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for changing the interrupt lockout */
|
||||
/* posture of the system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* new_posture New interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
// {
|
||||
.global _tx_thread_interrupt_control
|
||||
.thumb_func
|
||||
_tx_thread_interrupt_control:
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MRS r1, BASEPRI // Pickup current interrupt posture
|
||||
MSR BASEPRI, r0 // Apply the new interrupt posture
|
||||
MOV r0, r1 // Transfer old to return register
|
||||
#else
|
||||
MRS r1, PRIMASK // Pickup current interrupt lockout
|
||||
MSR PRIMASK, r0 // Apply the new interrupt lockout
|
||||
MOV r0, r1 // Transfer old to return register
|
||||
#endif
|
||||
BX lr // Return to caller
|
||||
// }
|
@ -0,0 +1,85 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_disable Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for disabling interrupts and returning */
|
||||
/* the previous interrupt lockout posture. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_disable(VOID)
|
||||
// {
|
||||
.global _tx_thread_interrupt_disable
|
||||
.thumb_func
|
||||
_tx_thread_interrupt_disable:
|
||||
/* Return current interrupt lockout posture. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MRS r0, BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
MRS r0, PRIMASK
|
||||
CPSID i
|
||||
#endif
|
||||
BX lr
|
||||
// }
|
@ -0,0 +1,82 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_restore Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for restoring the previous */
|
||||
/* interrupt lockout posture. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* previous_posture Previous interrupt posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_interrupt_restore(UINT previous_posture)
|
||||
// {
|
||||
.global _tx_thread_interrupt_restore
|
||||
.thumb_func
|
||||
_tx_thread_interrupt_restore:
|
||||
/* Restore previous interrupt lockout posture. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
MSR PRIMASK, r0
|
||||
#endif
|
||||
BX lr
|
||||
// }
|
331
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S
Normal file
331
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S
Normal file
@ -0,0 +1,331 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_thread_execute_ptr
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_execution_thread_enter
|
||||
.global _tx_execution_thread_exit
|
||||
#ifdef TX_LOW_POWER
|
||||
.global tx_low_power_enter
|
||||
.global tx_low_power_exit
|
||||
#endif
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Fixed predefined macro name, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
// {
|
||||
.global _tx_thread_schedule
|
||||
.thumb_func
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* This function should only ever be called on Cortex-M
|
||||
from the first schedule request. Subsequent scheduling occurs
|
||||
from the PendSV handling routine below. */
|
||||
|
||||
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
|
||||
|
||||
MOV r0, #0 // Build value for TX_FALSE
|
||||
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
STR r0, [r2, #0] // Clear preempt disable flag
|
||||
|
||||
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
|
||||
|
||||
#ifdef __ARM_FP
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #4 // Clear the FPCA bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
#endif
|
||||
|
||||
/* Enable interrupts */
|
||||
CPSIE i
|
||||
|
||||
/* Enter the scheduler for the first time. */
|
||||
|
||||
MOV r0, #0x10000000 // Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 // Load NVIC base
|
||||
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
|
||||
DSB // Complete all memory accesses
|
||||
ISB // Flush pipeline
|
||||
|
||||
/* Wait here for the PendSV to take place. */
|
||||
|
||||
__tx_wait_here:
|
||||
B __tx_wait_here // Wait for the PendSV to happen
|
||||
// }
|
||||
|
||||
/* Generic context switching PendSV handler. */
|
||||
|
||||
.global PendSV_Handler
|
||||
.global __tx_PendSVHandler
|
||||
.syntax unified
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
.thumb_func
|
||||
__tx_PendSVHandler:
|
||||
|
||||
/* Get current thread value and new thread pointer. */
|
||||
|
||||
__tx_ts_handler:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
PUSH {r0, lr} // Save LR (and r0 just for alignment)
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
POP {r0, lr} // Recover LR
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
#endif /* EXECUTION PROFILE */
|
||||
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
|
||||
MOV r3, #0 // Build NULL value
|
||||
LDR r1, [r0] // Pickup current thread pointer
|
||||
|
||||
/* Determine if there is a current thread to finish preserving. */
|
||||
|
||||
CBZ r1, __tx_ts_new // If NULL, skip preservation
|
||||
|
||||
/* Recover PSP and preserve current thread context. */
|
||||
|
||||
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
|
||||
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
|
||||
STMDB r12!, {r4-r11} // Save its remaining registers
|
||||
#ifdef __ARM_FP
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_save
|
||||
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
|
||||
_skip_vfp_save:
|
||||
#endif
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
STMDB r12!, {LR} // Save LR on the stack
|
||||
|
||||
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
|
||||
|
||||
LDR r5, [r4] // Pickup current time-slice
|
||||
STR r12, [r1, #8] // Save the thread stack pointer
|
||||
CBZ r5, __tx_ts_new // If not active, skip processing
|
||||
|
||||
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
|
||||
|
||||
STR r5, [r1, #24] // Save current time-slice
|
||||
|
||||
/* Clear the global time-slice. */
|
||||
|
||||
STR r3, [r4] // Clear time-slice
|
||||
|
||||
/* Executing thread is now completely preserved!!! */
|
||||
|
||||
__tx_ts_new:
|
||||
|
||||
/* Now we are looking for a new thread to execute! */
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Is there another thread ready to execute?
|
||||
CBZ r1, __tx_ts_wait // No, skip to the wait processing
|
||||
|
||||
/* Yes, another thread is ready for else, make the current thread the new thread. */
|
||||
|
||||
STR r1, [r0] // Setup the current thread pointer to the new thread
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
|
||||
/* Increment the thread run count. */
|
||||
|
||||
__tx_ts_restore:
|
||||
LDR r7, [r1, #4] // Pickup the current thread run count
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
LDR r5, [r1, #24] // Pickup thread's current time-slice
|
||||
ADD r7, r7, #1 // Increment the thread run count
|
||||
STR r7, [r1, #4] // Store the new run count
|
||||
|
||||
/* Setup global time-slice with thread's current time-slice. */
|
||||
|
||||
STR r5, [r4] // Setup global time-slice
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
PUSH {r0, r1} // Save r0 and r1
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
POP {r0, r1} // Recover r0 and r1
|
||||
#endif
|
||||
|
||||
/* Restore the thread context and PSP. */
|
||||
|
||||
LDR r12, [r1, #8] // Pickup thread's stack pointer
|
||||
LDMIA r12!, {LR} // Pickup LR
|
||||
#ifdef __ARM_FP
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_restore // If not, skip VFP restore
|
||||
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
|
||||
_skip_vfp_restore:
|
||||
#endif
|
||||
LDMIA r12!, {r4-r11} // Recover thread's registers
|
||||
MSR PSP, r12 // Setup the thread's stack pointer
|
||||
|
||||
/* Return to thread. */
|
||||
|
||||
BX lr // Return to thread!
|
||||
|
||||
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
|
||||
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
|
||||
are disabled to allow use of WFI for waiting for a thread to arrive. */
|
||||
|
||||
__tx_ts_wait:
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Pickup the next thread to execute pointer
|
||||
STR r1, [r0] // Store it in the current pointer
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_enter // Possibly enter low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB // Ensure no outstanding memory transactions
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#endif
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_exit // Exit low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
B __tx_ts_wait // Loop to continue waiting
|
||||
|
||||
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
|
||||
already in the handler! */
|
||||
|
||||
__tx_ts_ready:
|
||||
MOV r7, #0x08000000 // Build clear PendSV value
|
||||
MOV r8, #0xE000E000 // Build base NVIC address
|
||||
STR r7, [r8, #0xD04] // Clear any PendSV
|
||||
|
||||
/* Re-enable interrupts and restore new thread. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
B __tx_ts_restore // Restore the thread
|
||||
// }
|
||||
|
||||
#ifdef __ARM_FP
|
||||
|
||||
.global tx_thread_fpu_enable
|
||||
.thumb_func
|
||||
tx_thread_fpu_enable:
|
||||
.global tx_thread_fpu_disable
|
||||
.thumb_func
|
||||
tx_thread_fpu_disable:
|
||||
|
||||
/* Automatic VPF logic is supported, this function is present only for
|
||||
backward compatibility purposes and therefore simply returns. */
|
||||
|
||||
BX LR // Return to caller
|
||||
|
||||
#endif
|
139
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_stack_build.S
Normal file
139
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_stack_build.S
Normal file
@ -0,0 +1,139 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
// {
|
||||
.global _tx_thread_stack_build
|
||||
.thumb_func
|
||||
_tx_thread_stack_build:
|
||||
|
||||
/* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
on the Cortex-M should look like the following after it is built:
|
||||
|
||||
Stack Top:
|
||||
LR Interrupted LR (LR at time of PENDSV)
|
||||
r4 Initial value for r4
|
||||
r5 Initial value for r5
|
||||
r6 Initial value for r6
|
||||
r7 Initial value for r7
|
||||
r8 Initial value for r8
|
||||
r9 Initial value for r9
|
||||
r10 Initial value for r10
|
||||
r11 Initial value for r11
|
||||
r0 Initial value for r0 (Hardware stack starts here!!)
|
||||
r1 Initial value for r1
|
||||
r2 Initial value for r2
|
||||
r3 Initial value for r3
|
||||
r12 Initial value for r12
|
||||
lr Initial value for lr
|
||||
pc Initial value for pc
|
||||
xPSR Initial value for xPSR
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR r2, [r0, #16] // Pickup end of stack area
|
||||
BIC r2, r2, #0x7 // Align frame for 8-byte alignment
|
||||
SUB r2, r2, #68 // Subtract frame size
|
||||
LDR r3, =0xFFFFFFFD // Build initial LR value
|
||||
STR r3, [r2, #0] // Save on the stack
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #4] // Store initial r4
|
||||
STR r3, [r2, #8] // Store initial r5
|
||||
STR r3, [r2, #12] // Store initial r6
|
||||
STR r3, [r2, #16] // Store initial r7
|
||||
STR r3, [r2, #20] // Store initial r8
|
||||
STR r3, [r2, #24] // Store initial r9
|
||||
STR r3, [r2, #28] // Store initial r10
|
||||
STR r3, [r2, #32] // Store initial r11
|
||||
|
||||
/* Hardware stack follows. */
|
||||
|
||||
STR r3, [r2, #36] // Store initial r0
|
||||
STR r3, [r2, #40] // Store initial r1
|
||||
STR r3, [r2, #44] // Store initial r2
|
||||
STR r3, [r2, #48] // Store initial r3
|
||||
STR r3, [r2, #52] // Store initial r12
|
||||
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
|
||||
STR r3, [r2, #56] // Store initial lr
|
||||
STR r1, [r2, #60] // Store initial pc
|
||||
MOV r3, #0x01000000 // Only T-bit need be set
|
||||
STR r3, [r2, #64] // Store initial xPSR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
// thread_ptr -> tx_thread_stack_ptr = r2;
|
||||
|
||||
STR r2, [r0, #8] // Save stack pointer in thread's
|
||||
// control block
|
||||
BX lr // Return to caller
|
||||
// }
|
99
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S
Normal file
99
ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S
Normal file
@ -0,0 +1,99 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is target processor specific. It is used to transfer */
|
||||
/* control from a thread back to the ThreadX system. Only a */
|
||||
/* minimal context is saved since the compiler assumes temp registers */
|
||||
/* are going to get slicked by a function call anyway. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling loop */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_system_return(VOID)
|
||||
// {
|
||||
.thumb_func
|
||||
.global _tx_thread_system_return
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Return to real scheduler via PendSV. Note that this routine is often
|
||||
replaced with in-line assembly in tx_port.h to improved performance. */
|
||||
|
||||
MOV r0, #0x10000000 // Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 // Load NVIC base
|
||||
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
|
||||
MRS r0, IPSR // Pickup IPSR
|
||||
CMP r0, #0 // Is it a thread returning?
|
||||
BNE _isr_context // If ISR, skip interrupt enable
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
|
||||
MOV r0, #0
|
||||
MSR BASEPRI, r0 // Enable interrupts
|
||||
MSR BASEPRI, r1 // Restore original interrupt posture
|
||||
#else
|
||||
MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
|
||||
CPSIE i // Enable interrupts
|
||||
MSR PRIMASK, r1 // Restore original interrupt posture
|
||||
#endif
|
||||
_isr_context:
|
||||
BX lr // Return to caller
|
||||
// }
|
261
ports_arch/ARMv7-M/threadx/gnu/src/tx_timer_interrupt.S
Normal file
261
ports_arch/ARMv7-M/threadx/gnu/src/tx_timer_interrupt.S
Normal file
@ -0,0 +1,261 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Timer */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_timer_system_clock
|
||||
.global _tx_timer_current_ptr
|
||||
.global _tx_timer_list_start
|
||||
.global _tx_timer_list_end
|
||||
.global _tx_timer_expired_time_slice
|
||||
.global _tx_timer_expired
|
||||
.global _tx_thread_time_slice
|
||||
.global _tx_timer_expiration_process
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt Cortex-Mx/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* expiration functions are called. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_expiration_process Timer expiration processing */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), added */
|
||||
/* TX_NO_TIMER support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 03-08-2023 Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_timer_interrupt(VOID)
|
||||
// {
|
||||
#ifndef TX_NO_TIMER
|
||||
.global _tx_timer_interrupt
|
||||
.thumb_func
|
||||
_tx_timer_interrupt:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that the compiler scratch registers are available
|
||||
for use. */
|
||||
|
||||
/* Increment the system clock. */
|
||||
// _tx_timer_system_clock++;
|
||||
|
||||
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
|
||||
LDR r0, [r1, #0] // Pickup system clock
|
||||
ADD r0, r0, #1 // Increment system clock
|
||||
STR r0, [r1, #0] // Store new system clock
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
// if (_tx_timer_time_slice)
|
||||
// {
|
||||
|
||||
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
|
||||
LDR r2, [r3, #0] // Pickup time-slice
|
||||
CBZ r2, __tx_timer_no_time_slice // Is it non-active?
|
||||
// Yes, skip time-slice processing
|
||||
|
||||
/* Decrement the time_slice. */
|
||||
// _tx_timer_time_slice--;
|
||||
|
||||
SUB r2, r2, #1 // Decrement the time-slice
|
||||
STR r2, [r3, #0] // Store new time-slice value
|
||||
|
||||
/* Check for expiration. */
|
||||
// if (__tx_timer_time_slice == 0)
|
||||
|
||||
CBNZ r2, __tx_timer_no_time_slice // Has it expired?
|
||||
// No, skip expiration processing
|
||||
|
||||
/* Set the time-slice expired flag. */
|
||||
// _tx_timer_expired_time_slice = TX_TRUE;
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
|
||||
MOV r0, #1 // Build expired value
|
||||
STR r0, [r3, #0] // Set time-slice expiration flag
|
||||
|
||||
// }
|
||||
|
||||
__tx_timer_no_time_slice:
|
||||
|
||||
/* Test for timer expiration. */
|
||||
// if (*_tx_timer_current_ptr)
|
||||
// {
|
||||
|
||||
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
|
||||
LDR r0, [r1, #0] // Pickup current timer
|
||||
LDR r2, [r0, #0] // Pickup timer list entry
|
||||
CBZ r2, __tx_timer_no_timer // Is there anything in the list?
|
||||
// No, just increment the timer
|
||||
|
||||
/* Set expiration flag. */
|
||||
// _tx_timer_expired = TX_TRUE;
|
||||
|
||||
LDR r3, =_tx_timer_expired // Pickup expiration flag address
|
||||
MOV r2, #1 // Build expired value
|
||||
STR r2, [r3, #0] // Set expired flag
|
||||
B __tx_timer_done // Finished timer processing
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
__tx_timer_no_timer:
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
// _tx_timer_current_ptr++;
|
||||
|
||||
ADD r0, r0, #4 // Move to next timer
|
||||
|
||||
/* Check for wrap-around. */
|
||||
// if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
|
||||
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
|
||||
LDR r2, [r3, #0] // Pickup list end
|
||||
CMP r0, r2 // Are we at list end?
|
||||
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
|
||||
|
||||
/* Wrap to beginning of list. */
|
||||
// _tx_timer_current_ptr = _tx_timer_list_start;
|
||||
|
||||
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
|
||||
LDR r0, [r3, #0] // Set current pointer to list start
|
||||
|
||||
__tx_timer_skip_wrap:
|
||||
|
||||
STR r0, [r1, #0] // Store new current timer pointer
|
||||
// }
|
||||
|
||||
__tx_timer_done:
|
||||
|
||||
/* See if anything has expired. */
|
||||
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
// {
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
|
||||
LDR r2, [r3, #0] // Pickup time-slice expired flag
|
||||
CBNZ r2, __tx_something_expired // Did a time-slice expire?
|
||||
// If non-zero, time-slice expired
|
||||
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
|
||||
LDR r0, [r1, #0] // Pickup timer expired flag
|
||||
CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
|
||||
// No, nothing expired
|
||||
|
||||
__tx_something_expired:
|
||||
|
||||
STMDB sp!, {r0, lr} // Save the lr register on the stack
|
||||
// and save r0 just to keep 8-byte alignment
|
||||
|
||||
/* Did a timer expire? */
|
||||
// if (_tx_timer_expired)
|
||||
// {
|
||||
|
||||
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
|
||||
LDR r0, [r1, #0] // Pickup timer expired flag
|
||||
CBZ r0, __tx_timer_dont_activate // Check for timer expiration
|
||||
// If not set, skip timer activation
|
||||
|
||||
/* Process timer expiration. */
|
||||
// _tx_timer_expiration_process();
|
||||
|
||||
BL _tx_timer_expiration_process // Call the timer expiration handling routine
|
||||
|
||||
// }
|
||||
__tx_timer_dont_activate:
|
||||
|
||||
/* Did time slice expire? */
|
||||
// if (_tx_timer_expired_time_slice)
|
||||
// {
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
|
||||
LDR r2, [r3, #0] // Pickup the actual flag
|
||||
CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
|
||||
// No, skip time-slice processing
|
||||
|
||||
/* Time slice interrupted thread. */
|
||||
// _tx_thread_time_slice();
|
||||
|
||||
BL _tx_thread_time_slice // Call time-slice processing
|
||||
LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
LDR r1, [r0] // Is the preempt disable flag set?
|
||||
CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup the current thread pointer
|
||||
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
|
||||
LDR r3, [r2] // Pickup the execute thread pointer
|
||||
LDR r0, =0xE000ED04 // Build address of control register
|
||||
LDR r2, =0x10000000 // Build value for PendSV bit
|
||||
CMP r1, r3 // Are they the same?
|
||||
BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
|
||||
STR r2, [r0] // Not the same, issue the PendSV for preemption
|
||||
__tx_timer_skip_time_slice:
|
||||
|
||||
// }
|
||||
|
||||
__tx_timer_not_ts_expiration:
|
||||
|
||||
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
|
||||
// the 8-byte stack alignment
|
||||
|
||||
// }
|
||||
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
DSB // Complete all memory access
|
||||
BX lr // Return to caller
|
||||
// }
|
||||
#endif
|
13
ports_arch/ARMv7-M/threadx/iar/example_build/azure_rtos.eww
Normal file
13
ports_arch/ARMv7-M/threadx/iar/example_build/azure_rtos.eww
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
|
||||
<workspace>
|
||||
<project>
|
||||
<path>$WS_DIR$\sample_threadx.ewp</path>
|
||||
</project>
|
||||
<project>
|
||||
<path>$WS_DIR$\tx.ewp</path>
|
||||
</project>
|
||||
<batchBuild/>
|
||||
</workspace>
|
||||
|
||||
|
72
ports_arch/ARMv7-M/threadx/iar/example_build/cstartup_M.s
Normal file
72
ports_arch/ARMv7-M/threadx/iar/example_build/cstartup_M.s
Normal file
@ -0,0 +1,72 @@
|
||||
EXTERN __iar_program_start
|
||||
PUBLIC __vector_table
|
||||
|
||||
SECTION .text:CODE:REORDER(1)
|
||||
|
||||
;; Keep vector table even if it's not referenced
|
||||
REQUIRE __vector_table
|
||||
|
||||
THUMB
|
||||
|
||||
;; Forward declaration of sections.
|
||||
SECTION CSTACK:DATA:NOROOT(3)
|
||||
SECTION .intvec:CODE:NOROOT(2)
|
||||
|
||||
DATA
|
||||
|
||||
__vector_table
|
||||
DCD sfe(CSTACK)
|
||||
DCD __Reset_Vector
|
||||
DCD NMI_Handler
|
||||
DCD HardFault_Handler
|
||||
DCD MemManage_Handler
|
||||
DCD BusFault_Handler
|
||||
DCD UsageFault_Handler
|
||||
DCD 0
|
||||
DCD 0
|
||||
DCD 0
|
||||
DCD 0
|
||||
DCD SVC_Handler
|
||||
DCD DebugMon_Handler
|
||||
DCD 0
|
||||
DCD PendSV_Handler
|
||||
DCD SysTick_Handler
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Default interrupt handlers.
|
||||
;;
|
||||
|
||||
PUBWEAK NMI_Handler
|
||||
PUBWEAK HardFault_Handler
|
||||
PUBWEAK MemManage_Handler
|
||||
PUBWEAK BusFault_Handler
|
||||
PUBWEAK UsageFault_Handler
|
||||
PUBWEAK SVC_Handler
|
||||
PUBWEAK DebugMon_Handler
|
||||
PUBWEAK PendSV_Handler
|
||||
PUBWEAK SysTick_Handler
|
||||
|
||||
SECTION .text:CODE:REORDER:NOROOT(1)
|
||||
THUMB
|
||||
__Reset_Vector:
|
||||
; CPSID i ; Disable interrupts
|
||||
B __iar_program_start
|
||||
|
||||
|
||||
NMI_Handler
|
||||
HardFault_Handler
|
||||
MemManage_Handler
|
||||
BusFault_Handler
|
||||
UsageFault_Handler
|
||||
SVC_Handler
|
||||
DebugMon_Handler
|
||||
PendSV_Handler
|
||||
SysTick_Handler
|
||||
Default_Handler
|
||||
__default_handler
|
||||
CALL_GRAPH_ROOT __default_handler, "interrupt"
|
||||
NOCALL __default_handler
|
||||
B __default_handler
|
||||
|
||||
END
|
389
ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.c
Normal file
389
ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.c
Normal file
@ -0,0 +1,389 @@
|
||||
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
|
||||
threads of different priorities, using a message queue, semaphore, mutex, event flags group,
|
||||
byte pool, and block pool. Please refer to Chapter 6 of the ThreadX User Guide for a complete
|
||||
description of this demonstration. */
|
||||
|
||||
#include "tx_api.h"
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
#define DEMO_BYTE_POOL_SIZE 9120
|
||||
#define DEMO_BLOCK_POOL_SIZE 100
|
||||
#define DEMO_QUEUE_SIZE 100
|
||||
|
||||
|
||||
/* Define the ThreadX object control blocks... */
|
||||
|
||||
TX_THREAD thread_0;
|
||||
TX_THREAD thread_1;
|
||||
TX_THREAD thread_2;
|
||||
TX_THREAD thread_3;
|
||||
TX_THREAD thread_4;
|
||||
TX_THREAD thread_5;
|
||||
TX_THREAD thread_6;
|
||||
TX_THREAD thread_7;
|
||||
TX_QUEUE queue_0;
|
||||
TX_SEMAPHORE semaphore_0;
|
||||
TX_MUTEX mutex_0;
|
||||
TX_EVENT_FLAGS_GROUP event_flags_0;
|
||||
TX_BYTE_POOL byte_pool_0;
|
||||
TX_BLOCK_POOL block_pool_0;
|
||||
|
||||
|
||||
/* Define byte pool memory. */
|
||||
|
||||
UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
|
||||
|
||||
|
||||
/* Define event buffer. */
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
UCHAR trace_buffer[0x10000];
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the counters used in the demo application... */
|
||||
|
||||
ULONG thread_0_counter;
|
||||
ULONG thread_1_counter;
|
||||
ULONG thread_1_messages_sent;
|
||||
ULONG thread_2_counter;
|
||||
ULONG thread_2_messages_received;
|
||||
ULONG thread_3_counter;
|
||||
ULONG thread_4_counter;
|
||||
ULONG thread_5_counter;
|
||||
ULONG thread_6_counter;
|
||||
ULONG thread_7_counter;
|
||||
|
||||
|
||||
/* Define thread prototypes. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input);
|
||||
void thread_1_entry(ULONG thread_input);
|
||||
void thread_2_entry(ULONG thread_input);
|
||||
void thread_3_and_4_entry(ULONG thread_input);
|
||||
void thread_5_entry(ULONG thread_input);
|
||||
void thread_6_and_7_entry(ULONG thread_input);
|
||||
|
||||
|
||||
/* Define main entry point. */
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
/* Please refer to Chapter 6 of the ThreadX User Guide for a complete
|
||||
description of this demonstration. */
|
||||
|
||||
|
||||
/* Enter the ThreadX kernel. */
|
||||
tx_kernel_enter();
|
||||
}
|
||||
|
||||
|
||||
/* Define what the initial system looks like. */
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
|
||||
CHAR *pointer = TX_NULL;
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
tx_trace_enable(trace_buffer, sizeof(trace_buffer), 32);
|
||||
#endif
|
||||
|
||||
/* Create a byte memory pool from which to allocate the thread stacks. */
|
||||
tx_byte_pool_create(&byte_pool_0, "byte pool 0", byte_pool_memory, DEMO_BYTE_POOL_SIZE);
|
||||
|
||||
/* Put system definition stuff in here, e.g. thread creates and other assorted
|
||||
create information. */
|
||||
|
||||
/* Allocate the stack for thread 0. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create the main thread. */
|
||||
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 1. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 1 and 2. These threads pass information through a ThreadX
|
||||
message queue. It is also interesting to note that these threads have a time
|
||||
slice. */
|
||||
tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
16, 16, 4, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 2. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
16, 16, 4, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 3. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
|
||||
An interesting thing here is that both threads share the same instruction area. */
|
||||
tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 4. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 5. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create thread 5. This thread simply pends on an event flag which will be set
|
||||
by thread_0. */
|
||||
tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 6. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
|
||||
tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 7. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the message queue. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
|
||||
|
||||
/* Create the message queue shared by threads 1 and 2. */
|
||||
tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
|
||||
|
||||
/* Create the semaphore used by threads 3 and 4. */
|
||||
tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
|
||||
|
||||
/* Create the event flags group used by threads 1 and 5. */
|
||||
tx_event_flags_create(&event_flags_0, "event flags 0");
|
||||
|
||||
/* Create the mutex used by thread 6 and 7 without priority inheritance. */
|
||||
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
|
||||
|
||||
/* Allocate the memory for a small block pool. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create a block memory pool to allocate a message buffer from. */
|
||||
tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
|
||||
|
||||
/* Allocate a block and release the block memory. */
|
||||
tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
|
||||
|
||||
/* Release the block back to the pool. */
|
||||
tx_block_release(pointer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Define the test threads. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This thread simply sits in while-forever-sleep loop. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_0_counter++;
|
||||
|
||||
/* Sleep for 10 ticks. */
|
||||
tx_thread_sleep(10);
|
||||
|
||||
/* Set event flag 0 to wakeup thread 5. */
|
||||
status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_1_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This thread simply sends messages to a queue shared by thread 2. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_1_counter++;
|
||||
|
||||
/* Send message to queue 0. */
|
||||
status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check completion status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Increment the message sent. */
|
||||
thread_1_messages_sent++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_2_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
ULONG received_message;
|
||||
UINT status;
|
||||
|
||||
/* This thread retrieves messages placed on the queue by thread 1. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_2_counter++;
|
||||
|
||||
/* Retrieve a message from the queue. */
|
||||
status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check completion status and make sure the message is what we
|
||||
expected. */
|
||||
if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
|
||||
break;
|
||||
|
||||
/* Otherwise, all is okay. Increment the received message count. */
|
||||
thread_2_messages_received++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_3_and_4_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This function is executed from thread 3 and thread 4. As the loop
|
||||
below shows, these function compete for ownership of semaphore_0. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
if (thread_input == 3)
|
||||
thread_3_counter++;
|
||||
else
|
||||
thread_4_counter++;
|
||||
|
||||
/* Get the semaphore with suspension. */
|
||||
status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Sleep for 2 ticks to hold the semaphore. */
|
||||
tx_thread_sleep(2);
|
||||
|
||||
/* Release the semaphore. */
|
||||
status = tx_semaphore_put(&semaphore_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_5_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG actual_flags;
|
||||
|
||||
|
||||
/* This thread simply waits for an event in a forever loop. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_5_counter++;
|
||||
|
||||
/* Wait for event flag 0. */
|
||||
status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
|
||||
&actual_flags, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if ((status != TX_SUCCESS) || (actual_flags != 0x1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_6_and_7_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This function is executed from thread 6 and thread 7. As the loop
|
||||
below shows, these function compete for ownership of mutex_0. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
if (thread_input == 6)
|
||||
thread_6_counter++;
|
||||
else
|
||||
thread_7_counter++;
|
||||
|
||||
/* Get the mutex with suspension. */
|
||||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Get the mutex again with suspension. This shows
|
||||
that an owning thread may retrieve the mutex it
|
||||
owns multiple times. */
|
||||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Sleep for 2 ticks to hold the mutex. */
|
||||
tx_thread_sleep(2);
|
||||
|
||||
/* Release the mutex. */
|
||||
status = tx_mutex_put(&mutex_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Release the mutex again. This will actually
|
||||
release ownership since it was obtained twice. */
|
||||
status = tx_mutex_put(&mutex_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
2974
ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewd
Normal file
2974
ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewd
Normal file
File diff suppressed because it is too large
Load Diff
2137
ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewp
Normal file
2137
ports_arch/ARMv7-M/threadx/iar/example_build/sample_threadx.ewp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,42 @@
|
||||
/*###ICF### Section handled by ICF editor, don't touch! ****/
|
||||
/*-Editor annotation file-*/
|
||||
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
|
||||
/*-Specials-*/
|
||||
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
|
||||
/*-Memory Regions-*/
|
||||
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
|
||||
define symbol __ICFEDIT_region_ROM_end__ = 0x0007FFFF;
|
||||
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
|
||||
define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
|
||||
/*-Sizes-*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x200;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x200;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
define symbol FlashConfig_start__= 0x00000400;
|
||||
define symbol FlashConfig_end__ = 0x0000040f;
|
||||
|
||||
define memory mem with size = 4G;
|
||||
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to (FlashConfig_start__ - 1)] | [from (FlashConfig_end__+1) to __ICFEDIT_region_ROM_end__];
|
||||
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
|
||||
|
||||
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
||||
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
||||
|
||||
define region FlashConfig_region = mem:[from FlashConfig_start__ to FlashConfig_end__];
|
||||
|
||||
initialize by copy { readwrite };
|
||||
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
|
||||
do not initialize { section .noinit };
|
||||
|
||||
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
||||
|
||||
place in ROM_region { readonly };
|
||||
place in RAM_region { readwrite,
|
||||
block CSTACK, block HEAP };
|
||||
|
||||
place in FlashConfig_region
|
||||
{section FlashConfig};
|
||||
|
||||
place in RAM_region { last section FREE_MEM};
|
||||
|
2752
ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp
Normal file
2752
ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,151 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
EXTERN _tx_thread_system_stack_ptr
|
||||
EXTERN _tx_initialize_unused_memory
|
||||
EXTERN _tx_timer_interrupt
|
||||
EXTERN __vector_table
|
||||
EXTERN _tx_execution_isr_enter
|
||||
EXTERN _tx_execution_isr_exit
|
||||
|
||||
SYSTEM_CLOCK EQU 25000000
|
||||
SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 100) -1)
|
||||
|
||||
RSEG FREE_MEM:DATA
|
||||
PUBLIC __tx_free_memory_start
|
||||
__tx_free_memory_start
|
||||
DS32 4
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Cortex-Mx/IAR */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), added */
|
||||
/* TX_NO_TIMER support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_initialize_low_level(VOID)
|
||||
// {
|
||||
PUBLIC _tx_initialize_low_level
|
||||
_tx_initialize_low_level:
|
||||
|
||||
/* Ensure that interrupts are disabled. */
|
||||
CPSID i
|
||||
|
||||
/* Set base of available memory to end of non-initialised RAM area. */
|
||||
LDR r0, =__tx_free_memory_start // Get end of non-initialized RAM area
|
||||
LDR r2, =_tx_initialize_unused_memory // Build address of unused memory pointer
|
||||
STR r0, [r2, #0] // Save first free memory address
|
||||
|
||||
/* Setup Vector Table Offset Register. */
|
||||
MOV r0, #0xE000E000 // Build address of NVIC registers
|
||||
LDR r1, =__vector_table // Pickup address of vector table
|
||||
STR r1, [r0, #0xD08] // Set vector table address
|
||||
|
||||
/* Set system stack pointer from vector value. */
|
||||
LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer
|
||||
LDR r1, =__vector_table // Pickup address of vector table
|
||||
LDR r1, [r1] // Pickup reset stack pointer
|
||||
STR r1, [r0] // Save system stack pointer
|
||||
|
||||
#ifndef TX_NO_TIMER
|
||||
/* Configure SysTick. */
|
||||
MOV r0, #0xE000E000 // Build address of NVIC registers
|
||||
LDR r1, =SYSTICK_CYCLES
|
||||
STR r1, [r0, #0x14] // Setup SysTick Reload Value
|
||||
MOV r1, #0x7 // Build SysTick Control Enable Value
|
||||
STR r1, [r0, #0x10] // Setup SysTick Control
|
||||
#endif
|
||||
|
||||
/* Configure handler priorities. */
|
||||
LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM
|
||||
STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers
|
||||
LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv
|
||||
STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers
|
||||
// Note: SVC must be lowest priority, which is 0xFF
|
||||
LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM
|
||||
STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers
|
||||
// Note: PnSV must be lowest priority, which is 0xFF
|
||||
|
||||
/* Return to caller. */
|
||||
BX lr
|
||||
// }
|
||||
|
||||
#ifndef TX_NO_TIMER
|
||||
PUBLIC SysTick_Handler
|
||||
PUBLIC __tx_SysTickHandler
|
||||
__tx_SysTickHandler:
|
||||
SysTick_Handler:
|
||||
// VOID SysTick_Handler(VOID)
|
||||
// {
|
||||
|
||||
PUSH {r0, lr}
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
#endif
|
||||
BL _tx_timer_interrupt
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
BL _tx_execution_isr_exit // Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX lr
|
||||
// }
|
||||
#endif
|
||||
END
|
215
ports_arch/ARMv7-M/threadx/iar/readme_threadx.txt
Normal file
215
ports_arch/ARMv7-M/threadx/iar/readme_threadx.txt
Normal file
@ -0,0 +1,215 @@
|
||||
Microsoft's Azure RTOS ThreadX for ARMv7-M
|
||||
(Cortex-M3, Cortex-M4, Cortex-M7)
|
||||
Using IAR EWARM Tools
|
||||
|
||||
|
||||
1. Building the ThreadX run-time Library
|
||||
|
||||
Building the ThreadX library is easy. First, open the Azure RTOS workspace
|
||||
azure_rtos.eww. Next, make the TX project the "active project" in the
|
||||
IAR Embedded Workbench and select the "Make" button. You should observe
|
||||
assembly and compilation of a series of ThreadX source files. This
|
||||
results in the ThreadX run-time library file tx.a, which is needed by
|
||||
the application.
|
||||
|
||||
|
||||
2. Demonstration System
|
||||
|
||||
The ThreadX demonstration is designed to execute under the IAR debugger under
|
||||
simulation.
|
||||
|
||||
Building the demonstration is easy; simply open the threadx.www workspace file,
|
||||
make the sample_threadx.ewp project the "active project" in the IAR Embedded
|
||||
Workbench, and select the "Make" button.
|
||||
|
||||
You should observe the compilation of sample_threadx.c (which is the demonstration
|
||||
application) and linking with tx.a. The resulting file sample_threadx.out is a
|
||||
binary ELF file that can be downloaded and executed on the IAR Windows-based
|
||||
Cortex-M simulator.
|
||||
|
||||
|
||||
3. System Initialization
|
||||
|
||||
The entry point in ThreadX for the Cortex-M using IAR tools is at label
|
||||
__iar_program_start. This is defined within the IAR compiler's startup code.
|
||||
In addition, this is where all static and global preset C variable
|
||||
initialization processing takes place.
|
||||
|
||||
The ThreadX tx_initialize_low_level.s file is responsible for setting up
|
||||
various system data structures, and a periodic timer interrupt source.
|
||||
By default, the vector area is defined at the top of cstartup_M.s, which is
|
||||
a slightly modified from the base IAR file.
|
||||
|
||||
The _tx_initialize_low_level function inside of tx_initialize_low_level.s
|
||||
also determines the first available address for use by the application, which
|
||||
is supplied as the sole input parameter to your application definition function,
|
||||
tx_application_define. To accomplish this, a section is created in
|
||||
tx_initialize_low_level.s called FREE_MEM, which must be located after all
|
||||
other RAM sections in memory.
|
||||
|
||||
|
||||
4. Register Usage and Stack Frames
|
||||
|
||||
The following defines the saved context stack frames for context switches
|
||||
that occur as a result of interrupt handling or from thread-level API calls.
|
||||
All suspended threads have the same stack frame in the Cortex-M version of
|
||||
ThreadX. The top of the suspended thread's stack is pointed to by
|
||||
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
|
||||
|
||||
Non-FPU Stack Frame:
|
||||
|
||||
Stack Offset Stack Contents
|
||||
|
||||
0x00 lr Interrupted lr (lr at time of PENDSV)
|
||||
0x04 r4 Software stacked GP registers
|
||||
0x08 r5
|
||||
0x0C r6
|
||||
0x10 r7
|
||||
0x14 r8
|
||||
0x18 r9
|
||||
0x1C r10
|
||||
0x20 r11
|
||||
0x24 r0 Hardware stacked registers
|
||||
0x28 r1
|
||||
0x2C r2
|
||||
0x30 r3
|
||||
0x34 r12
|
||||
0x38 lr
|
||||
0x3C pc
|
||||
0x40 xPSR
|
||||
|
||||
FPU Stack Frame (only interrupted thread with FPU enabled):
|
||||
|
||||
Stack Offset Stack Contents
|
||||
|
||||
0x00 lr Interrupted lr (lr at time of PENDSV)
|
||||
0x04 s16 Software stacked FPU registers
|
||||
0x08 s17
|
||||
0x0C s18
|
||||
0x10 s19
|
||||
0x14 s20
|
||||
0x18 s21
|
||||
0x1C s22
|
||||
0x20 s23
|
||||
0x24 s24
|
||||
0x28 s25
|
||||
0x2C s26
|
||||
0x30 s27
|
||||
0x34 s28
|
||||
0x38 s29
|
||||
0x3C s30
|
||||
0x40 s31
|
||||
0x44 r4 Software stacked registers
|
||||
0x48 r5
|
||||
0x4C r6
|
||||
0x50 r7
|
||||
0x54 r8
|
||||
0x58 r9
|
||||
0x5C r10
|
||||
0x60 r11
|
||||
0x64 r0 Hardware stacked registers
|
||||
0x68 r1
|
||||
0x6C r2
|
||||
0x70 r3
|
||||
0x74 r12
|
||||
0x78 lr
|
||||
0x7C pc
|
||||
0x80 xPSR
|
||||
0x84 s0 Hardware stacked FPU registers
|
||||
0x88 s1
|
||||
0x8C s2
|
||||
0x90 s3
|
||||
0x94 s4
|
||||
0x98 s5
|
||||
0x9C s6
|
||||
0xA0 s7
|
||||
0xA4 s8
|
||||
0xA8 s9
|
||||
0xAC s10
|
||||
0xB0 s11
|
||||
0xB4 s12
|
||||
0xB8 s13
|
||||
0xBC s14
|
||||
0xC0 s15
|
||||
0xC4 fpscr
|
||||
|
||||
|
||||
5. Improving Performance
|
||||
|
||||
The distribution version of ThreadX is built without any compiler
|
||||
optimizations. This makes it easy to debug because you can trace or set
|
||||
breakpoints inside of ThreadX itself. Of course, this costs some
|
||||
performance. To make it run faster, you can change the ThreadX library
|
||||
project to enable various compiler optimizations.
|
||||
|
||||
In addition, you can eliminate the ThreadX basic API error checking by
|
||||
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
|
||||
defined.
|
||||
|
||||
|
||||
6. Interrupt Handling
|
||||
|
||||
The Cortex-M vectors start at the label __vector_table and is defined in cstartup_M.s.
|
||||
The application may modify the vector area according to its needs.
|
||||
|
||||
|
||||
6.1 Managed Interrupts
|
||||
|
||||
ISRs for Cortex-M using the IAR tools can be written completely in C (or assembly
|
||||
language) without any calls to _tx_thread_context_save or _tx_thread_context_restore.
|
||||
These ISRs are allowed access to the ThreadX API that is available to ISRs.
|
||||
|
||||
ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
|
||||
|
||||
void your_C_isr(void)
|
||||
{
|
||||
|
||||
/* ISR processing goes here, including any needed function calls. */
|
||||
}
|
||||
|
||||
ISRs written in assembly language will take the form:
|
||||
|
||||
PUBLIC your_assembly_isr
|
||||
your_assembly_isr:
|
||||
|
||||
PUSH {r0, lr}
|
||||
|
||||
; ISR processing goes here, including any needed function calls.
|
||||
|
||||
POP {r0, lr}
|
||||
BX lr
|
||||
|
||||
|
||||
7. IAR Thread-safe Library Support
|
||||
|
||||
Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
|
||||
and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
|
||||
should have the following line added (if not already in place):
|
||||
|
||||
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
|
||||
|
||||
The project options "General Options -> Library Configuration" should also have the
|
||||
"Enable thread support in library" box selected.
|
||||
|
||||
|
||||
8. VFP Support
|
||||
|
||||
ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
|
||||
can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
|
||||
context - no additional setup by the application.
|
||||
|
||||
|
||||
9. Revision History
|
||||
|
||||
For generic code revision information, please refer to the readme_threadx_generic.txt
|
||||
file, which is included in your distribution. The following details the revision
|
||||
information associated with this specific port of ThreadX:
|
||||
|
||||
06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using IAR's ARM tools.
|
||||
|
||||
|
||||
Copyright(c) 1996-2021 Microsoft Corporation
|
||||
|
||||
|
||||
https://azure.com/rtos
|
||||
|
804
ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c
Normal file
804
ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c
Normal file
@ -0,0 +1,804 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** IAR Multithreaded Library Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Define IAR library for tools prior to version 8. */
|
||||
|
||||
#if (__VER__ < 8000000)
|
||||
|
||||
|
||||
/* IAR version 7 and below. */
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/* This implementation requires that the following macros are defined in the
|
||||
tx_port.h file and <yvals.h> is included with the following code segments:
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#include <yvals.h>
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
|
||||
#else
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
|
||||
#else
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#endif
|
||||
|
||||
This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
|
||||
application.
|
||||
|
||||
Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
|
||||
*/
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
|
||||
#include <yvals.h>
|
||||
|
||||
|
||||
#if _MULTI_THREAD
|
||||
|
||||
TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
|
||||
UINT __tx_iar_system_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_system_lock_no_mutexes;
|
||||
UINT __tx_iar_system_lock_internal_errors;
|
||||
UINT __tx_iar_system_lock_isr_caller;
|
||||
|
||||
|
||||
/* Define the TLS access function for the IAR library. */
|
||||
|
||||
void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
|
||||
{
|
||||
|
||||
char _DLIB_TLS_MEMORY *p = 0;
|
||||
|
||||
/* Is there a current thread? */
|
||||
if (_tx_thread_current_ptr)
|
||||
p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
|
||||
else
|
||||
p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
|
||||
p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
|
||||
return (void _DLIB_TLS_MEMORY *) p;
|
||||
}
|
||||
|
||||
|
||||
/* Define mutexes for IAR library. */
|
||||
|
||||
void __iar_system_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_LOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_system_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_system_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_system_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if _DLIB_FILE_DESCRIPTOR
|
||||
|
||||
TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
|
||||
UINT __tx_iar_file_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_file_lock_no_mutexes;
|
||||
UINT __tx_iar_file_lock_internal_errors;
|
||||
UINT __tx_iar_file_lock_isr_caller;
|
||||
|
||||
|
||||
void __iar_file_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_FLOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_file_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_file_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
#endif /* _DLIB_FILE_DESCRIPTOR */
|
||||
|
||||
#endif /* _MULTI_THREAD */
|
||||
|
||||
#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
|
||||
|
||||
#else /* IAR version 8 and above. */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
/* This implementation requires that the following macros are defined in the
|
||||
tx_port.h file and <yvals.h> is included with the following code segments:
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#include <yvals.h>
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
|
||||
#else
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
void *_tx_iar_create_per_thread_tls_area(void);
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
|
||||
void __iar_Initlocks(void);
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
|
||||
#else
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#endif
|
||||
|
||||
This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
|
||||
application.
|
||||
|
||||
Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
|
||||
*/
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
|
||||
#include <DLib_threads.h>
|
||||
|
||||
|
||||
void * __aeabi_read_tp();
|
||||
|
||||
void* _tx_iar_create_per_thread_tls_area();
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
|
||||
|
||||
#pragma section="__iar_tls$$DATA"
|
||||
|
||||
/* Define the TLS access function for the IAR library. */
|
||||
void * __aeabi_read_tp(void)
|
||||
{
|
||||
void *p = 0;
|
||||
TX_THREAD *thread_ptr = _tx_thread_current_ptr;
|
||||
if (thread_ptr)
|
||||
{
|
||||
p = thread_ptr->tx_thread_iar_tls_pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = __section_begin("__iar_tls$$DATA");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Define the TLS creation and destruction to use malloc/free. */
|
||||
|
||||
void* _tx_iar_create_per_thread_tls_area()
|
||||
{
|
||||
UINT tls_size = __iar_tls_size();
|
||||
|
||||
/* Get memory for TLS. */
|
||||
void *p = malloc(tls_size);
|
||||
|
||||
/* Initialize TLS-area and run constructors for objects in TLS */
|
||||
__iar_tls_init(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
|
||||
{
|
||||
/* Destroy objects living in TLS */
|
||||
__call_thread_dtors();
|
||||
free(tls_ptr);
|
||||
}
|
||||
|
||||
#ifndef _MAX_LOCK
|
||||
#define _MAX_LOCK 4
|
||||
#endif
|
||||
|
||||
static TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
|
||||
static UINT __tx_iar_system_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_system_lock_no_mutexes;
|
||||
UINT __tx_iar_system_lock_internal_errors;
|
||||
UINT __tx_iar_system_lock_isr_caller;
|
||||
|
||||
|
||||
/* Define mutexes for IAR library. */
|
||||
|
||||
void __iar_system_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_LOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_system_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_system_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_system_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
if (*m)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
if (*m)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if _DLIB_FILE_DESCRIPTOR
|
||||
|
||||
#include <stdio.h> /* Added to get access to FOPEN_MAX */
|
||||
#ifndef _MAX_FLOCK
|
||||
#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */
|
||||
#endif
|
||||
|
||||
|
||||
TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
|
||||
UINT __tx_iar_file_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_file_lock_no_mutexes;
|
||||
UINT __tx_iar_file_lock_internal_errors;
|
||||
UINT __tx_iar_file_lock_isr_caller;
|
||||
|
||||
|
||||
void __iar_file_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_FLOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_file_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_file_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
#endif /* _DLIB_FILE_DESCRIPTOR */
|
||||
|
||||
#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
|
||||
|
||||
#endif /* IAR version 8 and above. */
|
763
ports_arch/ARMv7-M/threadx/iar/src/tx_misra.s
Normal file
763
ports_arch/ARMv7-M/threadx/iar/src/tx_misra.s
Normal file
@ -0,0 +1,763 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** ThreadX MISRA Compliance */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define SHT_PROGBITS 0x1
|
||||
|
||||
EXTERN __aeabi_memset
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_thread_interrupt_disable
|
||||
EXTERN _tx_thread_interrupt_restore
|
||||
EXTERN _tx_thread_stack_analyze
|
||||
EXTERN _tx_thread_stack_error_handler
|
||||
EXTERN _tx_thread_system_state
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
EXTERN _tx_trace_buffer_current_ptr
|
||||
EXTERN _tx_trace_buffer_end_ptr
|
||||
EXTERN _tx_trace_buffer_start_ptr
|
||||
EXTERN _tx_trace_event_enable_bits
|
||||
EXTERN _tx_trace_full_notify_function
|
||||
EXTERN _tx_trace_header_ptr
|
||||
#endif
|
||||
|
||||
PUBLIC _tx_misra_always_true
|
||||
PUBLIC _tx_misra_block_pool_to_uchar_pointer_convert
|
||||
PUBLIC _tx_misra_byte_pool_to_uchar_pointer_convert
|
||||
PUBLIC _tx_misra_char_to_uchar_pointer_convert
|
||||
PUBLIC _tx_misra_const_char_to_char_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
PUBLIC _tx_misra_entry_to_uchar_pointer_convert
|
||||
#endif
|
||||
PUBLIC _tx_misra_indirect_void_to_uchar_pointer_convert
|
||||
PUBLIC _tx_misra_memset
|
||||
PUBLIC _tx_misra_message_copy
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
PUBLIC _tx_misra_object_to_uchar_pointer_convert
|
||||
#endif
|
||||
PUBLIC _tx_misra_pointer_to_ulong_convert
|
||||
PUBLIC _tx_misra_status_get
|
||||
PUBLIC _tx_misra_thread_stack_check
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
PUBLIC _tx_misra_time_stamp_get
|
||||
#endif
|
||||
PUBLIC _tx_misra_timer_indirect_to_void_pointer_convert
|
||||
PUBLIC _tx_misra_timer_pointer_add
|
||||
PUBLIC _tx_misra_timer_pointer_dif
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
PUBLIC _tx_misra_trace_event_insert
|
||||
#endif
|
||||
PUBLIC _tx_misra_uchar_pointer_add
|
||||
PUBLIC _tx_misra_uchar_pointer_dif
|
||||
PUBLIC _tx_misra_uchar_pointer_sub
|
||||
PUBLIC _tx_misra_uchar_to_align_type_pointer_convert
|
||||
PUBLIC _tx_misra_uchar_to_block_pool_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
PUBLIC _tx_misra_uchar_to_entry_pointer_convert
|
||||
PUBLIC _tx_misra_uchar_to_header_pointer_convert
|
||||
#endif
|
||||
PUBLIC _tx_misra_uchar_to_indirect_byte_pool_pointer_convert
|
||||
PUBLIC _tx_misra_uchar_to_indirect_uchar_pointer_convert
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
PUBLIC _tx_misra_uchar_to_object_pointer_convert
|
||||
#endif
|
||||
PUBLIC _tx_misra_uchar_to_void_pointer_convert
|
||||
PUBLIC _tx_misra_ulong_pointer_add
|
||||
PUBLIC _tx_misra_ulong_pointer_dif
|
||||
PUBLIC _tx_misra_ulong_pointer_sub
|
||||
PUBLIC _tx_misra_ulong_to_pointer_convert
|
||||
PUBLIC _tx_misra_ulong_to_thread_pointer_convert
|
||||
PUBLIC _tx_misra_user_timer_pointer_get
|
||||
PUBLIC _tx_misra_void_to_block_pool_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_byte_pool_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_event_flags_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_indirect_uchar_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_mutex_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_queue_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_semaphore_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_thread_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_uchar_pointer_convert
|
||||
PUBLIC _tx_misra_void_to_ulong_pointer_convert
|
||||
PUBLIC _tx_misra_ipsr_get
|
||||
PUBLIC _tx_misra_control_get
|
||||
PUBLIC _tx_misra_control_set
|
||||
#ifdef __ARMVFP__
|
||||
PUBLIC _tx_misra_fpccr_get
|
||||
PUBLIC _tx_misra_vfp_touch
|
||||
#endif
|
||||
|
||||
PUBLIC _tx_misra_event_flags_group_not_used
|
||||
PUBLIC _tx_misra_event_flags_set_notify_not_used
|
||||
PUBLIC _tx_misra_queue_not_used
|
||||
PUBLIC _tx_misra_queue_send_notify_not_used
|
||||
PUBLIC _tx_misra_semaphore_not_used
|
||||
PUBLIC _tx_misra_semaphore_put_notify_not_used
|
||||
PUBLIC _tx_misra_thread_entry_exit_notify_not_used
|
||||
PUBLIC _tx_misra_thread_not_used
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
PUBLIC _tx_version_id
|
||||
|
||||
SECTION `.data`:DATA:REORDER:NOROOT(2)
|
||||
DATA
|
||||
// 51 CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.1 MISRA C Compliant *";
|
||||
_tx_version_id:
|
||||
DC8 43H, 6FH, 70H, 79H, 72H, 69H, 67H, 68H
|
||||
DC8 74H, 20H, 28H, 63H, 29H, 20H, 31H, 39H
|
||||
DC8 39H, 36H, 2DH, 32H, 30H, 31H, 38H, 20H
|
||||
DC8 45H, 78H, 70H, 72H, 65H, 73H, 73H, 20H
|
||||
DC8 4CH, 6FH, 67H, 69H, 63H, 20H, 49H, 6EH
|
||||
DC8 63H, 2EH, 20H, 2AH, 20H, 54H, 68H, 72H
|
||||
DC8 65H, 61H, 64H, 58H, 20H, 36H, 2EH, 31H
|
||||
DC8 20H, 4DH, 49H, 53H, 52H, 41H, 20H, 43H
|
||||
DC8 20H, 43H, 6FH, 6DH, 70H, 6CH, 69H, 61H
|
||||
DC8 6EH, 74H, 20H, 2AH, 0
|
||||
DC8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
#endif //TX_MISRA_ENABLE
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_memset:
|
||||
PUSH {R4,LR}
|
||||
MOVS R4,R0
|
||||
MOVS R0,R2
|
||||
MOVS R2,R1
|
||||
MOVS R1,R0
|
||||
MOVS R0,R4
|
||||
BL __aeabi_memset
|
||||
POP {R4,PC} // return
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_uchar_pointer_add:
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_uchar_pointer_sub:
|
||||
RSBS R1,R1,#+0
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_uchar_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
/** */
|
||||
/** This single function serves all of the below prototypes. */
|
||||
/** */
|
||||
/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
|
||||
/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
|
||||
/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
|
||||
/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
|
||||
/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
|
||||
/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
|
||||
/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
|
||||
/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
|
||||
/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
|
||||
/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
|
||||
/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
|
||||
/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
|
||||
/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
|
||||
/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
|
||||
/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
|
||||
/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
|
||||
/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
|
||||
/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
|
||||
/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
|
||||
/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
|
||||
/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
|
||||
/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
|
||||
/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
|
||||
/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */
|
||||
/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */
|
||||
/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */
|
||||
/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */
|
||||
/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */
|
||||
/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */
|
||||
/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */
|
||||
/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */
|
||||
/** */
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_pointer_to_ulong_convert:
|
||||
_tx_misra_ulong_to_pointer_convert:
|
||||
_tx_misra_indirect_void_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_indirect_uchar_pointer_convert:
|
||||
_tx_misra_block_pool_to_uchar_pointer_convert:
|
||||
_tx_misra_void_to_block_pool_pointer_convert:
|
||||
_tx_misra_void_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_block_pool_pointer_convert:
|
||||
_tx_misra_void_to_indirect_uchar_pointer_convert:
|
||||
_tx_misra_void_to_byte_pool_pointer_convert:
|
||||
_tx_misra_byte_pool_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_align_type_pointer_convert:
|
||||
_tx_misra_uchar_to_indirect_byte_pool_pointer_convert:
|
||||
_tx_misra_void_to_event_flags_pointer_convert:
|
||||
_tx_misra_void_to_ulong_pointer_convert:
|
||||
_tx_misra_void_to_mutex_pointer_convert:
|
||||
_tx_misra_void_to_queue_pointer_convert:
|
||||
_tx_misra_void_to_semaphore_pointer_convert:
|
||||
_tx_misra_uchar_to_void_pointer_convert:
|
||||
_tx_misra_ulong_to_thread_pointer_convert:
|
||||
_tx_misra_timer_indirect_to_void_pointer_convert:
|
||||
_tx_misra_const_char_to_char_pointer_convert:
|
||||
_tx_misra_void_to_thread_pointer_convert:
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
_tx_misra_object_to_uchar_pointer_convert:
|
||||
_tx_misra_uchar_to_object_pointer_convert:
|
||||
_tx_misra_uchar_to_header_pointer_convert:
|
||||
_tx_misra_uchar_to_entry_pointer_convert:
|
||||
_tx_misra_entry_to_uchar_pointer_convert:
|
||||
#endif
|
||||
_tx_misra_char_to_uchar_pointer_convert:
|
||||
_tx_misra_event_flags_group_not_used:
|
||||
_tx_misra_event_flags_set_notify_not_used:
|
||||
_tx_misra_queue_not_used:
|
||||
_tx_misra_queue_send_notify_not_used:
|
||||
_tx_misra_semaphore_not_used:
|
||||
_tx_misra_semaphore_put_notify_not_used:
|
||||
_tx_misra_thread_entry_exit_notify_not_used:
|
||||
_tx_misra_thread_not_used:
|
||||
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_ulong_pointer_add:
|
||||
ADD R0,R0,R1, LSL #+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_ulong_pointer_sub:
|
||||
MVNS R2,#+3
|
||||
MULS R1,R2,R1
|
||||
ADD R0,R0,R1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_ulong_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
ASRS R0,R0,#+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
|
||||
/** UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_message_copy:
|
||||
PUSH {R4,R5}
|
||||
LDR R3,[R0, #+0]
|
||||
LDR R4,[R1, #+0]
|
||||
LDR R5,[R3, #+0]
|
||||
STR R5,[R4, #+0]
|
||||
ADDS R4,R4,#+4
|
||||
ADDS R3,R3,#+4
|
||||
CMP R2,#+2
|
||||
BCC.N ??_tx_misra_message_copy_0
|
||||
SUBS R2,R2,#+1
|
||||
B.N ??_tx_misra_message_copy_1
|
||||
??_tx_misra_message_copy_2:
|
||||
LDR R5,[R3, #+0]
|
||||
STR R5,[R4, #+0]
|
||||
ADDS R4,R4,#+4
|
||||
ADDS R3,R3,#+4
|
||||
SUBS R2,R2,#+1
|
||||
??_tx_misra_message_copy_1:
|
||||
CMP R2,#+0
|
||||
BNE.N ??_tx_misra_message_copy_2
|
||||
??_tx_misra_message_copy_0:
|
||||
STR R3,[R0, #+0]
|
||||
STR R4,[R1, #+0]
|
||||
POP {R4,R5}
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
|
||||
/** TX_TIMER_INTERNAL **ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_timer_pointer_dif:
|
||||
SUBS R0,R0,R1
|
||||
ASRS R0,R0,#+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
|
||||
/** **ptr1, ULONG size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_timer_pointer_add:
|
||||
ADD R0,R0,R1, LSL #+2
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
|
||||
/** *internal_timer, TX_TIMER **user_timer); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_user_timer_pointer_get:
|
||||
SUBS R0,#8
|
||||
STR R0,[R1, #+0]
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
|
||||
/** VOID **highest_stack); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_thread_stack_check:
|
||||
PUSH {R3-R5,LR}
|
||||
MOVS R4,R0
|
||||
MOVS R5,R1
|
||||
BL _tx_thread_interrupt_disable
|
||||
CMP R4,#+0
|
||||
BEQ.N ??_tx_misra_thread_stack_check_0
|
||||
LDR R1,[R4, #+0]
|
||||
LDR.N R2,??DataTable2 // 0x54485244
|
||||
CMP R1,R2
|
||||
BNE.N ??_tx_misra_thread_stack_check_0
|
||||
LDR R1,[R4, #+8]
|
||||
LDR R2,[R5, #+0]
|
||||
CMP R1,R2
|
||||
BCS.N ??_tx_misra_thread_stack_check_1
|
||||
LDR R1,[R4, #+8]
|
||||
STR R1,[R5, #+0]
|
||||
??_tx_misra_thread_stack_check_1:
|
||||
LDR R1,[R4, #+12]
|
||||
LDR R1,[R1, #+0]
|
||||
CMP R1,#-269488145
|
||||
BNE.N ??_tx_misra_thread_stack_check_2
|
||||
LDR R1,[R4, #+16]
|
||||
LDR R1,[R1, #+1]
|
||||
CMP R1,#-269488145
|
||||
BNE.N ??_tx_misra_thread_stack_check_2
|
||||
LDR R1,[R5, #+0]
|
||||
LDR R2,[R4, #+12]
|
||||
CMP R1,R2
|
||||
BCS.N ??_tx_misra_thread_stack_check_3
|
||||
??_tx_misra_thread_stack_check_2:
|
||||
BL _tx_thread_interrupt_restore
|
||||
MOVS R0,R4
|
||||
BL _tx_thread_stack_error_handler
|
||||
BL _tx_thread_interrupt_disable
|
||||
??_tx_misra_thread_stack_check_3:
|
||||
LDR R1,[R5, #+0]
|
||||
LDR R1,[R1, #-4]
|
||||
CMP R1,#-269488145
|
||||
BEQ.N ??_tx_misra_thread_stack_check_0
|
||||
BL _tx_thread_interrupt_restore
|
||||
MOVS R0,R4
|
||||
BL _tx_thread_stack_analyze
|
||||
BL _tx_thread_interrupt_disable
|
||||
??_tx_misra_thread_stack_check_0:
|
||||
BL _tx_thread_interrupt_restore
|
||||
POP {R0,R4,R5,PC} // return
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
|
||||
/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
|
||||
/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_trace_event_insert:
|
||||
PUSH {R3-R7,LR}
|
||||
LDR.N R4,??DataTable2_1
|
||||
LDR R4,[R4, #+0]
|
||||
CMP R4,#+0
|
||||
BEQ.N ??_tx_misra_trace_event_insert_0
|
||||
LDR.N R5,??DataTable2_2
|
||||
LDR R5,[R5, #+0]
|
||||
LDR R6,[SP, #+28]
|
||||
TST R5,R6
|
||||
BEQ.N ??_tx_misra_trace_event_insert_0
|
||||
LDR.N R5,??DataTable2_3
|
||||
LDR R5,[R5, #+0]
|
||||
LDR.N R6,??DataTable2_4
|
||||
LDR R6,[R6, #+0]
|
||||
CMP R5,#+0
|
||||
BNE.N ??_tx_misra_trace_event_insert_1
|
||||
LDR R5,[R6, #+44]
|
||||
LDR R7,[R6, #+60]
|
||||
LSLS R7,R7,#+16
|
||||
ORRS R7,R7,#0x80000000
|
||||
ORRS R5,R7,R5
|
||||
B.N ??_tx_misra_trace_event_insert_2
|
||||
??_tx_misra_trace_event_insert_1:
|
||||
CMP R5,#-252645136
|
||||
BCS.N ??_tx_misra_trace_event_insert_3
|
||||
MOVS R5,R6
|
||||
MOVS R6,#-1
|
||||
B.N ??_tx_misra_trace_event_insert_2
|
||||
??_tx_misra_trace_event_insert_3:
|
||||
MOVS R6,#-252645136
|
||||
MOVS R5,#+0
|
||||
??_tx_misra_trace_event_insert_2:
|
||||
STR R6,[R4, #+0]
|
||||
STR R5,[R4, #+4]
|
||||
STR R0,[R4, #+8]
|
||||
LDR R0,[SP, #+32]
|
||||
STR R0,[R4, #+12]
|
||||
STR R1,[R4, #+16]
|
||||
STR R2,[R4, #+20]
|
||||
STR R3,[R4, #+24]
|
||||
LDR R0,[SP, #+24]
|
||||
STR R0,[R4, #+28]
|
||||
ADDS R4,R4,#+32
|
||||
LDR.N R0,??DataTable2_5
|
||||
LDR R0,[R0, #+0]
|
||||
CMP R4,R0
|
||||
BCC.N ??_tx_misra_trace_event_insert_4
|
||||
LDR.N R0,??DataTable2_6
|
||||
LDR R4,[R0, #+0]
|
||||
LDR.N R0,??DataTable2_1
|
||||
STR R4,[R0, #+0]
|
||||
LDR.N R0,??DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
STR R4,[R0, #+32]
|
||||
LDR.N R0,??DataTable2_8
|
||||
LDR R0,[R0, #+0]
|
||||
CMP R0,#+0
|
||||
BEQ.N ??_tx_misra_trace_event_insert_0
|
||||
LDR.N R0,??DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
LDR.N R1,??DataTable2_8
|
||||
LDR R1,[R1, #+0]
|
||||
BLX R1
|
||||
B.N ??_tx_misra_trace_event_insert_0
|
||||
??_tx_misra_trace_event_insert_4:
|
||||
LDR.N R0,??DataTable2_1
|
||||
STR R4,[R0, #+0]
|
||||
LDR.N R0,??DataTable2_7
|
||||
LDR R0,[R0, #+0]
|
||||
STR R4,[R0, #+32]
|
||||
??_tx_misra_trace_event_insert_0:
|
||||
POP {R0,R4-R7,PC} // return
|
||||
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_1:
|
||||
DC32 _tx_trace_buffer_current_ptr
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_2:
|
||||
DC32 _tx_trace_event_enable_bits
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_5:
|
||||
DC32 _tx_trace_buffer_end_ptr
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_6:
|
||||
DC32 _tx_trace_buffer_start_ptr
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_7:
|
||||
DC32 _tx_trace_header_ptr
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_8:
|
||||
DC32 _tx_trace_full_notify_function
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_time_stamp_get(VOID); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_time_stamp_get:
|
||||
MOVS R0,#+0
|
||||
BX LR // return
|
||||
|
||||
#endif
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2:
|
||||
DC32 0x54485244
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_3:
|
||||
DC32 _tx_thread_system_state
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
??DataTable2_4:
|
||||
DC32 _tx_thread_current_ptr
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_always_true(void); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_always_true:
|
||||
MOVS R0,#+1
|
||||
BX LR // return
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_status_get(UINT status); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_status_get:
|
||||
MOVS R0,#+0
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ipsr_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_ipsr_get:
|
||||
MRS R0, IPSR
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_control_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_control_get:
|
||||
MRS R0, CONTROL
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** void _tx_misra_control_set(ULONG value); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_control_set:
|
||||
MSR CONTROL, R0
|
||||
BX LR // return
|
||||
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_fpccr_get(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
_tx_misra_fpccr_get:
|
||||
LDR r0, =0xE000EF34 // Build FPCCR address
|
||||
LDR r0, [r0] // Load FPCCR value
|
||||
BX LR // return
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** void _tx_misra_vfp_touch(void); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(1)
|
||||
THUMB
|
||||
_tx_misra_vfp_touch:
|
||||
vmov.f32 s0, s0
|
||||
BX LR // return
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, 0
|
||||
DATA
|
||||
DC32 0
|
||||
|
||||
END
|
@ -0,0 +1,78 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
EXTERN _tx_execution_isr_exit
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is only needed for legacy applications and it should */
|
||||
/* not be called in any new development on a Cortex-M. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* [_tx_execution_isr_exit] Execution profiling ISR exit */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_restore(VOID)
|
||||
// {
|
||||
PUBLIC _tx_thread_context_restore
|
||||
_tx_thread_context_restore:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the ISR exit function to indicate an ISR is complete. */
|
||||
PUSH {r0, lr} // Save return address
|
||||
BL _tx_execution_isr_exit // Call the ISR exit function
|
||||
POP {r0, lr} // Recover return address
|
||||
#endif
|
||||
|
||||
BX lr
|
||||
// }
|
||||
END
|
80
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_save.s
Normal file
80
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_context_save.s
Normal file
@ -0,0 +1,80 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
EXTERN _tx_execution_isr_enter
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is only needed for legacy applications and it should */
|
||||
/* not be called in any new development on a Cortex-M. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* [_tx_execution_isr_enter] Execution profiling ISR enter */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_save(VOID)
|
||||
// {
|
||||
PUBLIC _tx_thread_context_save
|
||||
_tx_thread_context_save:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the ISR enter function to indicate an ISR is starting. */
|
||||
PUSH {r0, lr} // Save return address
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {r0, lr} // Recover return address
|
||||
#endif
|
||||
|
||||
/* Context is already saved - just return. */
|
||||
|
||||
BX lr
|
||||
// }
|
||||
END
|
@ -0,0 +1,78 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for changing the interrupt lockout */
|
||||
/* posture of the system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* new_posture New interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
// {
|
||||
PUBLIC _tx_thread_interrupt_control
|
||||
_tx_thread_interrupt_control:
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MRS r1, BASEPRI // Pickup current interrupt posture
|
||||
MSR BASEPRI, r0 // Apply the new interrupt posture
|
||||
MOV r0, r1 // Transfer old to return register
|
||||
#else
|
||||
MRS r1, PRIMASK // Pickup current interrupt lockout
|
||||
MSR PRIMASK, r0 // Apply the new interrupt lockout
|
||||
MOV r0, r1 // Transfer old to return register
|
||||
#endif
|
||||
BX lr // Return to caller
|
||||
// }
|
||||
END
|
@ -0,0 +1,78 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_disable Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for disabling interrupts and returning */
|
||||
/* the previous interrupt lockout posture. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_disable(VOID)
|
||||
// {
|
||||
PUBLIC _tx_thread_interrupt_disable
|
||||
_tx_thread_interrupt_disable:
|
||||
/* Return current interrupt lockout posture. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MRS r0, BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
MRS r0, PRIMASK
|
||||
CPSID i
|
||||
#endif
|
||||
BX lr
|
||||
// }
|
||||
END
|
@ -0,0 +1,75 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_restore Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for restoring the previous */
|
||||
/* interrupt lockout posture. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* previous_posture Previous interrupt posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_interrupt_restore(UINT previous_posture)
|
||||
// {
|
||||
PUBLIC _tx_thread_interrupt_restore
|
||||
_tx_thread_interrupt_restore:
|
||||
/* Restore previous interrupt lockout posture. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
MSR PRIMASK, r0
|
||||
#endif
|
||||
BX lr
|
||||
// }
|
||||
END
|
318
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s
Normal file
318
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s
Normal file
@ -0,0 +1,318 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_thread_execute_ptr
|
||||
EXTERN _tx_timer_time_slice
|
||||
EXTERN _tx_thread_preempt_disable
|
||||
EXTERN _tx_execution_thread_enter
|
||||
EXTERN _tx_execution_thread_exit
|
||||
#ifdef TX_LOW_POWER
|
||||
EXTERN tx_low_power_enter
|
||||
EXTERN tx_low_power_exit
|
||||
#endif
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-Mx/IAR */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 04-25-2022 Scott Larson Added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
// {
|
||||
PUBLIC _tx_thread_schedule
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* This function should only ever be called on Cortex-M
|
||||
from the first schedule request. Subsequent scheduling occurs
|
||||
from the PendSV handling routine below. */
|
||||
|
||||
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
|
||||
|
||||
MOV r0, #0 // Build value for TX_FALSE
|
||||
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
STR r0, [r2, #0] // Clear preempt disable flag
|
||||
|
||||
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #4 // Clear the FPCA bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
#endif
|
||||
|
||||
/* Enable interrupts */
|
||||
CPSIE i
|
||||
|
||||
/* Enter the scheduler for the first time. */
|
||||
|
||||
MOV r0, #0x10000000 // Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 // Load NVIC base
|
||||
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
|
||||
DSB // Complete all memory accesses
|
||||
ISB // Flush pipeline
|
||||
|
||||
/* Wait here for the PendSV to take place. */
|
||||
|
||||
__tx_wait_here:
|
||||
B __tx_wait_here // Wait for the PendSV to happen
|
||||
// }
|
||||
|
||||
/* Generic context switching PendSV handler. */
|
||||
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC __tx_PendSVHandler
|
||||
PendSV_Handler:
|
||||
__tx_PendSVHandler:
|
||||
|
||||
/* Get current thread value and new thread pointer. */
|
||||
|
||||
__tx_ts_handler:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
PUSH {r0, lr} // Save LR (and r0 just for alignment)
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
POP {r0, lr} // Recover LR
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
#endif /* EXECUTION PROFILE */
|
||||
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
|
||||
MOV r3, #0 // Build NULL value
|
||||
LDR r1, [r0] // Pickup current thread pointer
|
||||
|
||||
/* Determine if there is a current thread to finish preserving. */
|
||||
|
||||
CBZ r1, __tx_ts_new // If NULL, skip preservation
|
||||
|
||||
/* Recover PSP and preserve current thread context. */
|
||||
|
||||
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
|
||||
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
|
||||
STMDB r12!, {r4-r11} // Save its remaining registers
|
||||
#ifdef __ARMVFP__
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_save
|
||||
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
|
||||
_skip_vfp_save:
|
||||
#endif
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
STMDB r12!, {LR} // Save LR on the stack
|
||||
|
||||
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
|
||||
|
||||
LDR r5, [r4] // Pickup current time-slice
|
||||
STR r12, [r1, #8] // Save the thread stack pointer
|
||||
CBZ r5, __tx_ts_new // If not active, skip processing
|
||||
|
||||
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
|
||||
|
||||
STR r5, [r1, #24] // Save current time-slice
|
||||
|
||||
/* Clear the global time-slice. */
|
||||
|
||||
STR r3, [r4] // Clear time-slice
|
||||
|
||||
/* Executing thread is now completely preserved!!! */
|
||||
|
||||
__tx_ts_new:
|
||||
|
||||
/* Now we are looking for a new thread to execute! */
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Is there another thread ready to execute?
|
||||
CBZ r1, __tx_ts_wait // No, skip to the wait processing
|
||||
|
||||
/* Yes, another thread is ready for else, make the current thread the new thread. */
|
||||
|
||||
STR r1, [r0] // Setup the current thread pointer to the new thread
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
|
||||
/* Increment the thread run count. */
|
||||
|
||||
__tx_ts_restore:
|
||||
LDR r7, [r1, #4] // Pickup the current thread run count
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
LDR r5, [r1, #24] // Pickup thread's current time-slice
|
||||
ADD r7, r7, #1 // Increment the thread run count
|
||||
STR r7, [r1, #4] // Store the new run count
|
||||
|
||||
/* Setup global time-slice with thread's current time-slice. */
|
||||
|
||||
STR r5, [r4] // Setup global time-slice
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
PUSH {r0, r1} // Save r0 and r1
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
POP {r0, r1} // Recover r0 and r1
|
||||
#endif
|
||||
|
||||
/* Restore the thread context and PSP. */
|
||||
|
||||
LDR r12, [r1, #8] // Pickup thread's stack pointer
|
||||
LDMIA r12!, {LR} // Pickup LR
|
||||
#ifdef __ARMVFP__
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_restore // If not, skip VFP restore
|
||||
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
|
||||
_skip_vfp_restore:
|
||||
#endif
|
||||
LDMIA r12!, {r4-r11} // Recover thread's registers
|
||||
MSR PSP, r12 // Setup the thread's stack pointer
|
||||
|
||||
/* Return to thread. */
|
||||
|
||||
BX lr // Return to thread!
|
||||
|
||||
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
|
||||
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
|
||||
are disabled to allow use of WFI for waiting for a thread to arrive. */
|
||||
|
||||
__tx_ts_wait:
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Pickup the next thread to execute pointer
|
||||
STR r1, [r0] // Store it in the current pointer
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_enter // Possibly enter low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB // Ensure no outstanding memory transactions
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#endif
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_exit // Exit low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
B __tx_ts_wait // Loop to continue waiting
|
||||
|
||||
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
|
||||
already in the handler! */
|
||||
|
||||
__tx_ts_ready:
|
||||
MOV r7, #0x08000000 // Build clear PendSV value
|
||||
MOV r8, #0xE000E000 // Build base NVIC address
|
||||
STR r7, [r8, #0xD04] // Clear any PendSV
|
||||
|
||||
/* Re-enable interrupts and restore new thread. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
B __tx_ts_restore // Restore the thread
|
||||
// }
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
|
||||
PUBLIC tx_thread_fpu_enable
|
||||
tx_thread_fpu_enable:
|
||||
PUBLIC tx_thread_fpu_disable
|
||||
tx_thread_fpu_disable:
|
||||
|
||||
/* Automatic VPF logic is supported, this function is present only for
|
||||
backward compatibility purposes and therefore simply returns. */
|
||||
|
||||
BX LR // Return to caller
|
||||
|
||||
#endif
|
||||
END
|
132
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_stack_build.s
Normal file
132
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_stack_build.s
Normal file
@ -0,0 +1,132 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
// {
|
||||
PUBLIC _tx_thread_stack_build
|
||||
_tx_thread_stack_build:
|
||||
|
||||
/* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
on the Cortex-M should look like the following after it is built:
|
||||
|
||||
Stack Top:
|
||||
LR Interrupted LR (LR at time of PENDSV)
|
||||
r4 Initial value for r4
|
||||
r5 Initial value for r5
|
||||
r6 Initial value for r6
|
||||
r7 Initial value for r7
|
||||
r8 Initial value for r8
|
||||
r9 Initial value for r9
|
||||
r10 Initial value for r10
|
||||
r11 Initial value for r11
|
||||
r0 Initial value for r0 (Hardware stack starts here!!)
|
||||
r1 Initial value for r1
|
||||
r2 Initial value for r2
|
||||
r3 Initial value for r3
|
||||
r12 Initial value for r12
|
||||
lr Initial value for lr
|
||||
pc Initial value for pc
|
||||
xPSR Initial value for xPSR
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR r2, [r0, #16] // Pickup end of stack area
|
||||
BIC r2, r2, #0x7 // Align frame for 8-byte alignment
|
||||
SUB r2, r2, #68 // Subtract frame size
|
||||
LDR r3, =0xFFFFFFFD // Build initial LR value
|
||||
STR r3, [r2, #0] // Save on the stack
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #4] // Store initial r4
|
||||
STR r3, [r2, #8] // Store initial r5
|
||||
STR r3, [r2, #12] // Store initial r6
|
||||
STR r3, [r2, #16] // Store initial r7
|
||||
STR r3, [r2, #20] // Store initial r8
|
||||
STR r3, [r2, #24] // Store initial r9
|
||||
STR r3, [r2, #28] // Store initial r10
|
||||
STR r3, [r2, #32] // Store initial r11
|
||||
|
||||
/* Hardware stack follows. */
|
||||
|
||||
STR r3, [r2, #36] // Store initial r0
|
||||
STR r3, [r2, #40] // Store initial r1
|
||||
STR r3, [r2, #44] // Store initial r2
|
||||
STR r3, [r2, #48] // Store initial r3
|
||||
STR r3, [r2, #52] // Store initial r12
|
||||
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
|
||||
STR r3, [r2, #56] // Store initial lr
|
||||
STR r1, [r2, #60] // Store initial pc
|
||||
MOV r3, #0x01000000 // Only T-bit need be set
|
||||
STR r3, [r2, #64] // Store initial xPSR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
// thread_ptr -> tx_thread_stack_ptr = r2;
|
||||
|
||||
STR r2, [r0, #8] // Save stack pointer in thread's
|
||||
// control block
|
||||
BX lr // Return to caller
|
||||
// }
|
||||
END
|
92
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s
Normal file
92
ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s
Normal file
@ -0,0 +1,92 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return Cortex-Mx/IAR */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is target processor specific. It is used to transfer */
|
||||
/* control from a thread back to the ThreadX system. Only a */
|
||||
/* minimal context is saved since the compiler assumes temp registers */
|
||||
/* are going to get slicked by a function call anyway. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling loop */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_system_return(VOID)
|
||||
// {
|
||||
PUBLIC _tx_thread_system_return
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Return to real scheduler via PendSV. Note that this routine is often
|
||||
replaced with in-line assembly in tx_port.h to improved performance. */
|
||||
|
||||
MOV r0, #0x10000000 // Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 // Load NVIC base
|
||||
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
|
||||
MRS r0, IPSR // Pickup IPSR
|
||||
CMP r0, #0 // Is it a thread returning?
|
||||
BNE _isr_context // If ISR, skip interrupt enable
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
|
||||
MOV r0, #0
|
||||
MSR BASEPRI, r0 // Enable interrupts
|
||||
MSR BASEPRI, r1 // Restore original interrupt posture
|
||||
#else
|
||||
MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
|
||||
CPSIE i // Enable interrupts
|
||||
MSR PRIMASK, r1 // Restore original interrupt posture
|
||||
#endif
|
||||
_isr_context:
|
||||
BX lr // Return to caller
|
||||
// }
|
||||
END
|
257
ports_arch/ARMv7-M/threadx/iar/src/tx_timer_interrupt.s
Normal file
257
ports_arch/ARMv7-M/threadx/iar/src/tx_timer_interrupt.s
Normal file
@ -0,0 +1,257 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Timer */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
EXTERN _tx_timer_time_slice
|
||||
EXTERN _tx_timer_system_clock
|
||||
EXTERN _tx_timer_current_ptr
|
||||
EXTERN _tx_timer_list_start
|
||||
EXTERN _tx_timer_list_end
|
||||
EXTERN _tx_timer_expired_time_slice
|
||||
EXTERN _tx_timer_expired
|
||||
EXTERN _tx_thread_time_slice
|
||||
EXTERN _tx_timer_expiration_process
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_thread_execute_ptr
|
||||
EXTERN _tx_thread_preempt_disable
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt Cortex-Mx/IAR */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* expiration functions are called. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_expiration_process Timer expiration processing */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), added */
|
||||
/* TX_NO_TIMER support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_timer_interrupt(VOID)
|
||||
// {
|
||||
#ifndef TX_NO_TIMER
|
||||
PUBLIC _tx_timer_interrupt
|
||||
_tx_timer_interrupt:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that the compiler scratch registers are available
|
||||
for use. */
|
||||
|
||||
/* Increment the system clock. */
|
||||
// _tx_timer_system_clock++;
|
||||
|
||||
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
|
||||
LDR r0, [r1, #0] // Pickup system clock
|
||||
ADD r0, r0, #1 // Increment system clock
|
||||
STR r0, [r1, #0] // Store new system clock
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
// if (_tx_timer_time_slice)
|
||||
// {
|
||||
|
||||
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
|
||||
LDR r2, [r3, #0] // Pickup time-slice
|
||||
CBZ r2, __tx_timer_no_time_slice // Is it non-active?
|
||||
// Yes, skip time-slice processing
|
||||
|
||||
/* Decrement the time_slice. */
|
||||
// _tx_timer_time_slice--;
|
||||
|
||||
SUB r2, r2, #1 // Decrement the time-slice
|
||||
STR r2, [r3, #0] // Store new time-slice value
|
||||
|
||||
/* Check for expiration. */
|
||||
// if (__tx_timer_time_slice == 0)
|
||||
|
||||
CBNZ r2, __tx_timer_no_time_slice // Has it expired?
|
||||
// No, skip expiration processing
|
||||
|
||||
/* Set the time-slice expired flag. */
|
||||
// _tx_timer_expired_time_slice = TX_TRUE;
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
|
||||
MOV r0, #1 // Build expired value
|
||||
STR r0, [r3, #0] // Set time-slice expiration flag
|
||||
|
||||
// }
|
||||
|
||||
__tx_timer_no_time_slice:
|
||||
|
||||
/* Test for timer expiration. */
|
||||
// if (*_tx_timer_current_ptr)
|
||||
// {
|
||||
|
||||
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
|
||||
LDR r0, [r1, #0] // Pickup current timer
|
||||
LDR r2, [r0, #0] // Pickup timer list entry
|
||||
CBZ r2, __tx_timer_no_timer // Is there anything in the list?
|
||||
// No, just increment the timer
|
||||
|
||||
/* Set expiration flag. */
|
||||
// _tx_timer_expired = TX_TRUE;
|
||||
|
||||
LDR r3, =_tx_timer_expired // Pickup expiration flag address
|
||||
MOV r2, #1 // Build expired value
|
||||
STR r2, [r3, #0] // Set expired flag
|
||||
B __tx_timer_done // Finished timer processing
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
__tx_timer_no_timer:
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
// _tx_timer_current_ptr++;
|
||||
|
||||
ADD r0, r0, #4 // Move to next timer
|
||||
|
||||
/* Check for wrap-around. */
|
||||
// if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
|
||||
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
|
||||
LDR r2, [r3, #0] // Pickup list end
|
||||
CMP r0, r2 // Are we at list end?
|
||||
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
|
||||
|
||||
/* Wrap to beginning of list. */
|
||||
// _tx_timer_current_ptr = _tx_timer_list_start;
|
||||
|
||||
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
|
||||
LDR r0, [r3, #0] // Set current pointer to list start
|
||||
|
||||
__tx_timer_skip_wrap:
|
||||
|
||||
STR r0, [r1, #0] // Store new current timer pointer
|
||||
// }
|
||||
|
||||
__tx_timer_done:
|
||||
|
||||
/* See if anything has expired. */
|
||||
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
// {
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
|
||||
LDR r2, [r3, #0] // Pickup time-slice expired flag
|
||||
CBNZ r2, __tx_something_expired // Did a time-slice expire?
|
||||
// If non-zero, time-slice expired
|
||||
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
|
||||
LDR r0, [r1, #0] // Pickup timer expired flag
|
||||
CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
|
||||
// No, nothing expired
|
||||
|
||||
__tx_something_expired:
|
||||
|
||||
STMDB sp!, {r0, lr} // Save the lr register on the stack
|
||||
// and save r0 just to keep 8-byte alignment
|
||||
|
||||
/* Did a timer expire? */
|
||||
// if (_tx_timer_expired)
|
||||
// {
|
||||
|
||||
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
|
||||
LDR r0, [r1, #0] // Pickup timer expired flag
|
||||
CBZ r0, __tx_timer_dont_activate // Check for timer expiration
|
||||
// If not set, skip timer activation
|
||||
|
||||
/* Process timer expiration. */
|
||||
// _tx_timer_expiration_process();
|
||||
|
||||
BL _tx_timer_expiration_process // Call the timer expiration handling routine
|
||||
|
||||
// }
|
||||
__tx_timer_dont_activate:
|
||||
|
||||
/* Did time slice expire? */
|
||||
// if (_tx_timer_expired_time_slice)
|
||||
// {
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
|
||||
LDR r2, [r3, #0] // Pickup the actual flag
|
||||
CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
|
||||
// No, skip time-slice processing
|
||||
|
||||
/* Time slice interrupted thread. */
|
||||
// _tx_thread_time_slice();
|
||||
|
||||
BL _tx_thread_time_slice // Call time-slice processing
|
||||
LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
LDR r1, [r0] // Is the preempt disable flag set?
|
||||
CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup the current thread pointer
|
||||
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
|
||||
LDR r3, [r2] // Pickup the execute thread pointer
|
||||
LDR r0, =0xE000ED04 // Build address of control register
|
||||
LDR r2, =0x10000000 // Build value for PendSV bit
|
||||
CMP r1, r3 // Are they the same?
|
||||
BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
|
||||
STR r2, [r0] // Not the same, issue the PendSV for preemption
|
||||
__tx_timer_skip_time_slice:
|
||||
|
||||
// }
|
||||
|
||||
__tx_timer_not_ts_expiration:
|
||||
|
||||
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
|
||||
// the 8-byte stack alignment
|
||||
|
||||
// }
|
||||
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
DSB // Complete all memory access
|
||||
BX lr // Return to caller
|
||||
// }
|
||||
#endif
|
||||
END
|
563
ports_arch/ARMv7-M/threadx/iar/tx_low_power.c
Normal file
563
ports_arch/ARMv7-M/threadx/iar/tx_low_power.c
Normal file
@ -0,0 +1,563 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Low Power Timer Management */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_timer.h"
|
||||
#include "tx_low_power.h"
|
||||
|
||||
|
||||
/* Define low power global variables. */
|
||||
|
||||
/* Flag to determine if we've entered low power mode or not. */
|
||||
UINT tx_low_power_entered;
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* tx_low_power_enter PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the low power entry function. This function is */
|
||||
/* assumed to be called from the idle loop of tx_thread_schedule. It */
|
||||
/* is important to note that if an interrupt managed by ThreadX occurs */
|
||||
/* anywhere where interrupts are enabled in this function, the entire */
|
||||
/* processing of this function is discarded and the function won't be */
|
||||
/* re-entered until the idle loop in tx_thread_schedule is executed */
|
||||
/* again. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* tx_timer_get_next Get next timer expiration */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling loop */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID tx_low_power_enter(VOID)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
ULONG tx_low_power_next_expiration;
|
||||
ULONG any_expired;
|
||||
|
||||
|
||||
/* The below macro is user-defined code to determine
|
||||
if low power mode is beneficial for the application.
|
||||
Reasons for not entering low power mode include
|
||||
the overhead associated with entering and exiting low power mode
|
||||
outweighs the savings given when the next interrupt is expected.
|
||||
In addition, the application might also be in a state where
|
||||
responsiveness is more important than power savings. In such
|
||||
situations, using a "reduced power mode" might make more sense.
|
||||
In any case, if low power mode is not desired, simply return at
|
||||
this point in the code. */
|
||||
#ifdef TX_LOW_POWER_USER_CHECK
|
||||
TX_LOW_POWER_USER_CHECK;
|
||||
#endif
|
||||
|
||||
/* Disable interrupts while we prepare for low power mode. */
|
||||
TX_DISABLE
|
||||
|
||||
/* At this point, we want to enter low power mode, since nothing
|
||||
meaningful is going on in the system. However, in order to keep
|
||||
the ThreadX timer services accurate, we must first determine the
|
||||
next ThreadX timer expiration in terms of ticks. This is
|
||||
accomplished via the tx_timer_get_next API. */
|
||||
any_expired = tx_timer_get_next(&tx_low_power_next_expiration);
|
||||
|
||||
/* There are two possibilities:
|
||||
1: A ThreadX timer is active. tx_timer_get_next returns TX_TRUE.
|
||||
Program the hardware timer source such that the next timer
|
||||
interrupt is equal to: tx_low_power_next_expiration*tick_frequency.
|
||||
In most applications, the tick_frequency is 10ms, but this is
|
||||
completely application specific in ThreadX, typically set up
|
||||
in tx_low_level_initialize.
|
||||
2: There are no ThreadX timers active. tx_timer_get_next returns TX_FALSE.
|
||||
If you don't care about maintaining the ThreadX system clock, you can simply
|
||||
sleep forever (until an interrupt wakes you up).
|
||||
If you do want to maintain the ThreadX system clock,
|
||||
program the hardware timer so you can keep track of elapsed time. */
|
||||
#ifdef TX_LOW_POWER_USER_TIMER_SETUP
|
||||
TX_LOW_POWER_USER_TIMER_SETUP(any_expired, tx_low_power_next_expiration);
|
||||
#endif
|
||||
|
||||
|
||||
/* Set the flag indicating that low power has been entered. This
|
||||
flag is checked in tx_low_power_exit to determine if the logic
|
||||
used to adjust the ThreadX time is required. */
|
||||
tx_low_power_entered = TX_TRUE;
|
||||
|
||||
/* Re-enable interrupts before low power mode is entered. */
|
||||
TX_RESTORE
|
||||
|
||||
/* User code to enter low power mode. */
|
||||
#ifdef TX_LOW_POWER_USER_ENTER
|
||||
TX_LOW_POWER_USER_ENTER;
|
||||
#endif
|
||||
|
||||
/* If the low power code returns, this routine returns to the
|
||||
tx_thread_schedule loop. */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* tx_low_power_exit PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the low power exit function. This function must */
|
||||
/* be called from any interrupt that can wakeup the processor from */
|
||||
/* low power mode. If nothing needs to be done, this function simply */
|
||||
/* returns. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* tx_time_increment Update the ThreadX timer */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Front-end of Interrupt */
|
||||
/* Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID tx_low_power_exit(VOID)
|
||||
{
|
||||
ULONG tx_low_power_adjust_ticks;
|
||||
|
||||
/* Determine if the interrupt occurred in low power mode. */
|
||||
if (tx_low_power_entered)
|
||||
{
|
||||
|
||||
/* Yes, low power mode was interrupted. */
|
||||
|
||||
/* Clear the low power entered flag. */
|
||||
tx_low_power_entered = TX_FALSE;
|
||||
|
||||
/* User code to exit low power mode and reprogram the
|
||||
timer to the desired interrupt frequency. */
|
||||
#ifdef TX_LOW_POWER_USER_EXIT
|
||||
TX_LOW_POWER_USER_EXIT;
|
||||
#endif
|
||||
|
||||
/* User code to determine how many timer ticks (interrupts) that
|
||||
the ThreadX time should be incremented to properly adjust
|
||||
for the time in low power mode. The result is assumed to be
|
||||
placed in tx_low_power_adjust_ticks. */
|
||||
#ifdef TX_LOW_POWER_USER_TIMER_ADJUST
|
||||
tx_low_power_adjust_ticks = TX_LOW_POWER_USER_TIMER_ADJUST;
|
||||
#else
|
||||
tx_low_power_adjust_ticks = (ULONG)0;
|
||||
#endif
|
||||
|
||||
/* Determine if the ThreadX timer needs incrementing. */
|
||||
if (tx_low_power_adjust_ticks)
|
||||
{
|
||||
|
||||
/* Yes, the ThreadX time must be incremented. Call tx_time_increment
|
||||
to accomplish this. */
|
||||
tx_time_increment(tx_low_power_adjust_ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* tx_timer_get_next PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calculates the next expiration time minus 1 tick for */
|
||||
/* the currently active ThreadX timers. If no timer is active, this */
|
||||
/* routine will return a value of TX_FALSE and the next ticks value */
|
||||
/* will be set to zero. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* next_timer_tick_ptr Pointer to destination for next */
|
||||
/* timer expiration value */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_TRUE (1) At least one timer is active */
|
||||
/* TX_FALSE (0) No timers are currently active */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* tx_low_power_enter */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG tx_timer_get_next(ULONG *next_timer_tick_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_TIMER_INTERNAL **timer_list_head;
|
||||
TX_TIMER_INTERNAL *next_timer;
|
||||
UINT i;
|
||||
ULONG calculated_time;
|
||||
ULONG expiration_time = (ULONG) 0xFFFFFFFF;
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Look at the next timer entry. */
|
||||
timer_list_head = _tx_timer_current_ptr;
|
||||
|
||||
/* Loop through the timer list, looking for the first non-NULL
|
||||
value to signal an active timer. */
|
||||
for (i = (UINT)0; i < TX_TIMER_ENTRIES; i++)
|
||||
{
|
||||
|
||||
/* Now determine if there is an active timer in this slot. */
|
||||
if (*timer_list_head)
|
||||
{
|
||||
|
||||
/* Setup the pointer to the expiration list. */
|
||||
next_timer = *timer_list_head;
|
||||
|
||||
/* Loop through the timers active for this relative time slot (determined by i). */
|
||||
do
|
||||
{
|
||||
|
||||
/* Determine if the remaining time is larger than the list. */
|
||||
if (next_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
|
||||
{
|
||||
|
||||
/* Calculate the expiration time. */
|
||||
calculated_time = next_timer -> tx_timer_internal_remaining_ticks - (TX_TIMER_ENTRIES - i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Calculate the expiration time, which is simply the number of entries in this case. */
|
||||
calculated_time = i;
|
||||
}
|
||||
|
||||
/* Determine if a new minimum expiration time is present. */
|
||||
if (expiration_time > calculated_time)
|
||||
{
|
||||
|
||||
/* Yes, a new minimum expiration time is present - remember it! */
|
||||
expiration_time = calculated_time;
|
||||
}
|
||||
|
||||
/* Move to the next entry in the timer list. */
|
||||
next_timer = next_timer -> tx_timer_internal_active_next;
|
||||
|
||||
} while (next_timer != *timer_list_head);
|
||||
}
|
||||
|
||||
/* This timer entry is NULL, so just move to the next one. */
|
||||
timer_list_head++;
|
||||
|
||||
/* Check for timer list wrap condition. */
|
||||
if (timer_list_head >= _tx_timer_list_end)
|
||||
{
|
||||
|
||||
/* Wrap to the beginning of the list. */
|
||||
timer_list_head = _tx_timer_list_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Determine if an active timer was found. */
|
||||
if (expiration_time != 0xFFFFFFFF)
|
||||
{
|
||||
|
||||
/* Yes, an active timer was found. */
|
||||
*next_timer_tick_ptr = expiration_time;
|
||||
return(TX_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No active timer was found. */
|
||||
*next_timer_tick_ptr = 0;
|
||||
return(TX_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* tx_time_increment PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function increments the current time by a specified value. */
|
||||
/* The value was derived by the application by calling the */
|
||||
/* tx_timer_get_next function prior to this call, which was right */
|
||||
/* before the processor was put in sleep mode. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* time_increment The amount of time to catch up on */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_system_activate Timer activate service */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* tx_low_power_exit */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID tx_time_increment(ULONG time_increment)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT i;
|
||||
TX_TIMER_INTERNAL **timer_list_head;
|
||||
TX_TIMER_INTERNAL *next_timer;
|
||||
TX_TIMER_INTERNAL *temp_list_head;
|
||||
|
||||
|
||||
/* Determine if there is any time increment. */
|
||||
if (time_increment == 0)
|
||||
{
|
||||
|
||||
/* Nothing to do, just return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Adjust the system clock. */
|
||||
_tx_timer_system_clock = _tx_timer_system_clock + time_increment;
|
||||
|
||||
/* Adjust the time slice variable. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
/* Decrement the time-slice variable. */
|
||||
if (_tx_timer_time_slice > time_increment)
|
||||
_tx_timer_time_slice = _tx_timer_time_slice - time_increment;
|
||||
else
|
||||
_tx_timer_time_slice = 1;
|
||||
}
|
||||
|
||||
/* Calculate the proper place to position the timer. */
|
||||
timer_list_head = _tx_timer_current_ptr;
|
||||
|
||||
/* Setup the temporary list pointer. */
|
||||
temp_list_head = TX_NULL;
|
||||
|
||||
/* Loop to pull all timers off the timer structure and put on the
|
||||
the temporary list head. */
|
||||
for (i = 0; i < TX_TIMER_ENTRIES; i++)
|
||||
{
|
||||
|
||||
/* Determine if there is a timer list in this entry. */
|
||||
if (*timer_list_head)
|
||||
{
|
||||
|
||||
/* Walk the list and update all the relative times to actual times. */
|
||||
|
||||
/* Setup the pointer to the expiration list. */
|
||||
next_timer = *timer_list_head;
|
||||
|
||||
/* Loop through the timers active for this relative time slot (determined by i). */
|
||||
do
|
||||
{
|
||||
|
||||
/* Determine if the remaining time is larger than the list. */
|
||||
if (next_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
|
||||
{
|
||||
|
||||
/* Calculate the actual expiration time. */
|
||||
next_timer -> tx_timer_internal_remaining_ticks =
|
||||
next_timer -> tx_timer_internal_remaining_ticks - (TX_TIMER_ENTRIES - i) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Calculate the expiration time, which is simply the number of entries in this
|
||||
case. */
|
||||
next_timer -> tx_timer_internal_remaining_ticks = i + 1;
|
||||
}
|
||||
|
||||
/* Move to the next entry in the timer list. */
|
||||
next_timer = next_timer -> tx_timer_internal_active_next;
|
||||
|
||||
} while (next_timer != *timer_list_head);
|
||||
|
||||
/* NULL terminate the current timer list. */
|
||||
((*timer_list_head) -> tx_timer_internal_active_previous) -> tx_timer_internal_active_next = TX_NULL;
|
||||
|
||||
/* Yes, determine if the temporary list is NULL. */
|
||||
if (temp_list_head == TX_NULL)
|
||||
{
|
||||
|
||||
/* First item on the list. Move the entire
|
||||
linked list. */
|
||||
temp_list_head = *timer_list_head;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, the temp list already has timers on it. Link the next
|
||||
timer list to the end. */
|
||||
(temp_list_head -> tx_timer_internal_active_previous) -> tx_timer_internal_active_next = *timer_list_head;
|
||||
|
||||
/* Now update the previous to the new list's previous timer pointer. */
|
||||
temp_list_head -> tx_timer_internal_active_previous = (*timer_list_head) -> tx_timer_internal_active_previous;
|
||||
}
|
||||
|
||||
/* Now clear the current timer head pointer. */
|
||||
*timer_list_head = TX_NULL;
|
||||
}
|
||||
|
||||
/* Move to next timer entry. */
|
||||
timer_list_head++;
|
||||
|
||||
/* Determine if a wrap around condition has occurred. */
|
||||
if (timer_list_head >= _tx_timer_list_end)
|
||||
{
|
||||
|
||||
/* Wrap from the beginning of the list. */
|
||||
timer_list_head = _tx_timer_list_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the current timer pointer to the beginning of the list. */
|
||||
_tx_timer_current_ptr = _tx_timer_list_start;
|
||||
|
||||
/* Loop to update and reinsert all the timers in the list. */
|
||||
while (temp_list_head)
|
||||
{
|
||||
|
||||
/* Pickup the next timer to update and reinsert. */
|
||||
next_timer = temp_list_head;
|
||||
|
||||
/* Move the temp list head pointer to the next pointer. */
|
||||
temp_list_head = next_timer -> tx_timer_internal_active_next;
|
||||
|
||||
/* Determine if the remaining time is greater than the time increment
|
||||
value - this is the normal case. */
|
||||
if (next_timer -> tx_timer_internal_remaining_ticks > time_increment)
|
||||
{
|
||||
|
||||
/* Decrement the elapsed time. */
|
||||
next_timer -> tx_timer_internal_remaining_ticks = next_timer -> tx_timer_internal_remaining_ticks - time_increment;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Simply set the expiration value to expire on the next tick. */
|
||||
next_timer -> tx_timer_internal_remaining_ticks = 1;
|
||||
}
|
||||
|
||||
/* Now clear the timer list head pointer for the timer activate function to work properly. */
|
||||
next_timer -> tx_timer_internal_list_head = TX_NULL;
|
||||
|
||||
/* Now re-insert the timer into the list. */
|
||||
_tx_timer_system_activate(next_timer);
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
58
ports_arch/ARMv7-M/threadx/iar/tx_low_power.h
Normal file
58
ports_arch/ARMv7-M/threadx/iar/tx_low_power.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Timer Management */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_low_power.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines prototypes for the low-power timer additions */
|
||||
/* required for sleep mode. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_LOW_POWER_H
|
||||
#define TX_LOW_POWER_H
|
||||
|
||||
|
||||
/* Define low-power function prototypes. */
|
||||
|
||||
VOID tx_low_power_enter(VOID);
|
||||
VOID tx_low_power_exit(VOID);
|
||||
VOID tx_time_increment(ULONG time_increment);
|
||||
ULONG tx_timer_get_next(ULONG *next_timer_tick_ptr);
|
||||
|
||||
#endif
|
729
ports_arch/ARMv7-M/threadx/inc/tx_port.h
Normal file
729
ports_arch/ARMv7-M/threadx/inc/tx_port.h
Normal file
@ -0,0 +1,729 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-Mx */
|
||||
/* 6.1.12 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
|
||||
/* the ARMv7-M architecture and compilers into one common file. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Modified comments, updated */
|
||||
/* typedef to fix misra */
|
||||
/* violation, */
|
||||
/* fixed predefined macro, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* 07-29-2022 Scott Larson Modified comments and */
|
||||
/* described BASEPRI usage, */
|
||||
/* resulting in version 6.1.12 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||
alternately be defined on the command line. */
|
||||
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __ICCARM__
|
||||
#include <intrinsics.h> /* IAR Intrinsics */
|
||||
#define __asm__ __asm /* Define to make all inline asm look similar */
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#include <yvals.h>
|
||||
#endif
|
||||
#endif /* __ICCARM__ */
|
||||
|
||||
#ifdef __ghs__
|
||||
#include <arm_ghs.h>
|
||||
#include "tx_ghs.h"
|
||||
#endif /* __ghs__ */
|
||||
|
||||
|
||||
#if !defined(__GNUC__) && !defined(__CC_ARM)
|
||||
#define __get_control_value __get_CONTROL
|
||||
#define __set_control_value __set_CONTROL
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __get_ipsr_value __get_IPSR
|
||||
#endif
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long long ULONG64;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
#define ULONG64_DEFINED
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts.
|
||||
If using BASEPRI is desired, define the following two symbols for both c and assembly files:
|
||||
TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK.
|
||||
TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask.
|
||||
Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run.
|
||||
*/
|
||||
|
||||
/* Define various constants for the ThreadX Cortex-M port. */
|
||||
|
||||
#define TX_INT_DISABLE 1 /* Disable interrupts */
|
||||
#define TX_INT_ENABLE 0 /* Enable interrupts */
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
|
||||
#endif
|
||||
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
#ifdef __ghs__
|
||||
/* Define constants for Green Hills EventAnalyzer. */
|
||||
|
||||
/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
|
||||
represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
|
||||
|
||||
#define TX_EL_TICKS_PER_SECOND 1000000
|
||||
|
||||
/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
|
||||
simulate the time-stamp source with a counter. */
|
||||
|
||||
#define read_tbu() _tx_el_time_base_upper
|
||||
#define read_tbl() ++_tx_el_time_base_lower
|
||||
#endif /* __ghs__ */
|
||||
|
||||
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||
how the ThreadX library was built. */
|
||||
|
||||
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0)
|
||||
|
||||
|
||||
/* Define the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
#define TX_DISABLE_INLINE
|
||||
#else
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
logic. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
#define TX_THREAD_EXTENSION_1
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
|
||||
#elif defined(__ghs__)
|
||||
#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
|
||||
int Errno; /* errno. */ \
|
||||
char * strtok_saved_pos; /* strtok() position. */
|
||||
#else
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#endif
|
||||
|
||||
|
||||
#define TX_THREAD_EXTENSION_3
|
||||
|
||||
|
||||
|
||||
/* Define the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
additional is needed for this port so it is defined as white space. */
|
||||
|
||||
#ifndef TX_THREAD_USER_EXTENSION
|
||||
#define TX_THREAD_USER_EXTENSION
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#if (__VER__ < 8000000)
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
|
||||
#else
|
||||
void *_tx_iar_create_per_thread_tls_area(void);
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
|
||||
void __iar_Initlocks(void);
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
|
||||
#endif
|
||||
#else
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#endif
|
||||
|
||||
#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
|
||||
ULONG _tx_misra_control_get(void);
|
||||
void _tx_misra_control_set(ULONG value);
|
||||
ULONG _tx_misra_fpccr_get(void);
|
||||
void _tx_misra_vfp_touch(void);
|
||||
|
||||
#else /* TX_MISRA_ENABLE not defined */
|
||||
|
||||
/* Define some helper functions (these are intrinsics in some compilers). */
|
||||
#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
|
||||
{
|
||||
ULONG control_value;
|
||||
|
||||
__asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
|
||||
return(control_value);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
|
||||
{
|
||||
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
|
||||
}
|
||||
|
||||
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
|
||||
|
||||
#elif defined(__CC_ARM) /* ARM Compiler 5 */
|
||||
|
||||
__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
|
||||
{
|
||||
ULONG control_value;
|
||||
|
||||
__asm volatile ("MRS control_value,CONTROL");
|
||||
return(control_value);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
|
||||
{
|
||||
__asm__ volatile ("MSR CONTROL,control_value");
|
||||
}
|
||||
/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
|
||||
void _tx_vfp_access(void);
|
||||
#define TX_VFP_TOUCH() _tx_vfp_access();
|
||||
|
||||
#elif defined(__ICCARM__) /* IAR */
|
||||
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
|
||||
#endif /* Helper functions for different compilers */
|
||||
|
||||
#endif /* TX_MISRA_ENABLE */
|
||||
|
||||
|
||||
/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
|
||||
in order to ensure no lazy stacking will occur. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = __get_control_value(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
__set_control_value(_tx_vfp_state); \
|
||||
}
|
||||
#else
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_misra_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_misra_control_set(_tx_vfp_state); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
|
||||
If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
|
||||
this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
|
||||
the lazy FPU save, then restore the CONTROL.FPCA state. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_system_state; \
|
||||
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
|
||||
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = __get_control_value(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
__set_control_value(_tx_vfp_state); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = __get_control_value(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
|
||||
TX_VFP_TOUCH(); \
|
||||
if (_tx_vfp_state == ((ULONG) 0)) \
|
||||
{ \
|
||||
_tx_vfp_state = __get_control_value(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
__set_control_value(_tx_vfp_state); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_system_state; \
|
||||
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
|
||||
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_misra_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_misra_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = _tx_misra_fpccr_get(); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_misra_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
|
||||
_tx_misra_vfp_touch(); \
|
||||
if (_tx_vfp_state == ((ULONG) 0)) \
|
||||
{ \
|
||||
_tx_vfp_state = _tx_misra_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_misra_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* No VFP in use */
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
#ifdef __CC_ARM /* ARM Compiler 5 */
|
||||
|
||||
register unsigned int _ipsr __asm("ipsr");
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
|
||||
|
||||
#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
|
||||
{
|
||||
unsigned int ipsr_value;
|
||||
__asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
|
||||
return(ipsr_value);
|
||||
}
|
||||
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
|
||||
|
||||
#elif defined(__ICCARM__) /* IAR */
|
||||
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
|
||||
|
||||
#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
|
||||
|
||||
#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
|
||||
ULONG _tx_misra_ipsr_get(VOID);
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
|
||||
#endif /* TX_MISRA_ENABLE */
|
||||
#endif /* TX_THREAD_GET_SYSTEM_STATE */
|
||||
|
||||
|
||||
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
|
||||
indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
|
||||
for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
|
||||
zero after initialization for Cortex-M ports. */
|
||||
|
||||
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
|
||||
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
|
||||
#endif
|
||||
|
||||
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
|
||||
prevent early scheduling on Cortex-M parts. */
|
||||
|
||||
#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
|
||||
#ifdef __ICCARM__ /* IAR Compiler */
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
|
||||
#elif defined(__CC_ARM) /* AC5 Compiler */
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
|
||||
#elif defined(__GNUC__) /* GCC and AC6 Compiler */
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
|
||||
__asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Define the interrupt disable/restore macros for each compiler. */
|
||||
|
||||
#if defined(__GNUC__) || defined(__ICCARM__)
|
||||
|
||||
/*** GCC/AC6 and IAR ***/
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
|
||||
{
|
||||
unsigned int posture;
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
|
||||
#else
|
||||
__asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
|
||||
#endif
|
||||
return(posture);
|
||||
}
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
|
||||
{
|
||||
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
|
||||
}
|
||||
#else
|
||||
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
|
||||
{
|
||||
__asm__ volatile ("CPSIE i": : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
|
||||
{
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__set_basepri_value(int_posture);
|
||||
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
|
||||
#else
|
||||
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
unsigned int int_posture;
|
||||
|
||||
int_posture = __get_interrupt_posture();
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__set_basepri_value(TX_PORT_BASEPRI);
|
||||
#else
|
||||
__asm__ volatile ("CPSID i" : : : "memory");
|
||||
#endif
|
||||
return(int_posture);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_posture();
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__set_basepri_value(0);
|
||||
#else
|
||||
__enable_interrupts();
|
||||
#endif
|
||||
__restore_interrupt(interrupt_save);
|
||||
}
|
||||
}
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupt(interrupt_save);
|
||||
|
||||
/*** End GCC/AC6 and IAR ***/
|
||||
|
||||
#elif defined(__CC_ARM)
|
||||
|
||||
/*** AC5 ***/
|
||||
|
||||
static __inline unsigned int __get_interrupt_posture(void)
|
||||
{
|
||||
unsigned int posture;
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__asm__ volatile ("MRS #posture, BASEPRI");
|
||||
#else
|
||||
__asm__ volatile ("MRS #posture, PRIMASK");
|
||||
#endif
|
||||
return(posture);
|
||||
}
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
static __inline void __set_basepri_value(unsigned int basepri_value)
|
||||
{
|
||||
__asm__ volatile ("MSR BASEPRI, #basepri_value");
|
||||
}
|
||||
#endif
|
||||
|
||||
static __inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
unsigned int int_posture;
|
||||
|
||||
int_posture = __get_interrupt_posture();
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__set_basepri_value(TX_PORT_BASEPRI);
|
||||
#else
|
||||
__asm__ volatile ("CPSID i");
|
||||
#endif
|
||||
return(int_posture);
|
||||
}
|
||||
|
||||
static __inline void __restore_interrupt(unsigned int int_posture)
|
||||
{
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
__set_basepri_value(int_posture);
|
||||
#else
|
||||
__asm__ volatile ("MSR PRIMASK, #int_posture");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _tx_thread_system_return_inline(void)
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_ipsr == 0)
|
||||
{
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
interrupt_save = __get_interrupt_posture();
|
||||
__set_basepri_value(0);
|
||||
__set_basepri_value(interrupt_save);
|
||||
#else
|
||||
interrupt_save = __disable_irq();
|
||||
__enable_irq();
|
||||
if (interrupt_save != 0)
|
||||
__disable_irq();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupt(interrupt_save);
|
||||
|
||||
/*** End AC5 ***/
|
||||
|
||||
#endif /* Interrupt disable/restore macros for each compiler. */
|
||||
|
||||
/* Redefine _tx_thread_system_return for improved performance. */
|
||||
|
||||
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||
|
||||
|
||||
#else /* TX_DISABLE_INLINE is defined */
|
||||
|
||||
UINT _tx_thread_interrupt_disable(VOID);
|
||||
VOID _tx_thread_interrupt_restore(UINT previous_posture);
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||
#endif /* TX_DISABLE_INLINE */
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
void tx_thread_fpu_disable(void);
|
||||
|
||||
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-Mx Version 6.2.1 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,109 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
IMPORT __use_two_region_memory
|
||||
IMPORT __scatterload
|
||||
IMPORT txm_heap
|
||||
|
||||
AREA ||.text||, CODE, READONLY
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_initialize Cortex-Mx/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the module c runtime. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* __scatterload Initialize C runtime */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Start module thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _txm_module_initialize(VOID)
|
||||
|
||||
EXPORT _txm_module_initialize
|
||||
_txm_module_initialize
|
||||
PUSH {r4-r12,lr} // Save dregs and LR
|
||||
|
||||
B __scatterload // Call ARM func to initialize variables
|
||||
|
||||
|
||||
/* Override __rt_exit function. */
|
||||
|
||||
EXPORT __rt_exit
|
||||
__rt_exit
|
||||
|
||||
POP {r4-r12,lr} // Restore dregs and LR
|
||||
BX lr // Return to caller
|
||||
|
||||
EXPORT __user_setup_stackheap
|
||||
// returns heap start address in R0
|
||||
// returns heap end address in R2
|
||||
// does not touch SP, it is already set up before the module runs
|
||||
|
||||
__user_setup_stackheap
|
||||
LDR r1, _tx_heap_offset // load heap offset
|
||||
ADD r0, r9, r1 // calculate heap base address
|
||||
MOV r2, #TXM_MODULE_HEAP_SIZE // load heap size
|
||||
ADD r2, r2, r0 // calculate heap end address
|
||||
BX lr
|
||||
|
||||
ALIGN 4
|
||||
_tx_heap_offset
|
||||
DCDO txm_heap
|
||||
AREA ||.arm_vfe_header||, DATA, READONLY, NOALLOC, ALIGN=2
|
||||
|
||||
IMPORT txm_heap [DATA]
|
||||
|
||||
|
||||
// Dummy main function
|
||||
|
||||
AREA section_main, CODE, READONLY, ALIGN=2
|
||||
EXPORT main
|
||||
main
|
||||
BX lr
|
||||
|
||||
END
|
@ -0,0 +1,174 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TXM_MODULE
|
||||
#define TXM_MODULE
|
||||
#endif
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define TX_SOURCE_CODE
|
||||
#endif
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "txm_module.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/* Define the global module entry pointer from the start thread of the module. */
|
||||
|
||||
TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
|
||||
|
||||
|
||||
/* Define the dispatch function pointer used in the module implementation. */
|
||||
|
||||
ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
|
||||
|
||||
|
||||
/* Define the startup code that clears the uninitialized global data and sets up the
|
||||
preset global variables. */
|
||||
|
||||
extern VOID _txm_module_initialize(VOID);
|
||||
|
||||
__align(8) UCHAR txm_heap[TXM_MODULE_HEAP_SIZE];
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Cortex-Mx/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calls the specified entry function of the thread. It */
|
||||
/* also provides a place for the thread's entry function to return. */
|
||||
/* If the thread returns, this function places the thread in a */
|
||||
/* "COMPLETED" state. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to current thread */
|
||||
/* thread_info Pointer to thread entry info */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_initialize cstartup initialization */
|
||||
/* thread_entry Thread's entry function */
|
||||
/* tx_thread_resume Resume the module callback thread */
|
||||
/* _txm_module_thread_system_suspend Module thread suspension routine */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Initial thread stack frame */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*entry_exit_notify)(TX_THREAD *, UINT);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine if this is the start thread. If so, we must prepare the module for
|
||||
execution. If not, simply skip the C startup code. */
|
||||
if (thread_info -> txm_module_thread_entry_info_start_thread)
|
||||
{
|
||||
/* Initialize the C environment. */
|
||||
_txm_module_initialize();
|
||||
|
||||
/* Save the entry info pointer, for later use. */
|
||||
_txm_module_entry_info = thread_info;
|
||||
|
||||
/* Save the kernel function dispatch address. This is used to make all resident calls from
|
||||
the module. */
|
||||
_txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
|
||||
|
||||
/* Ensure that we have a valid pointer. */
|
||||
while (!_txm_module_kernel_call_dispatcher)
|
||||
{
|
||||
/* Loop here, if an error is present getting the dispatch function pointer!
|
||||
An error here typically indicates the resident portion of _tx_thread_schedule
|
||||
is not supporting the trap to obtain the function pointer. */
|
||||
}
|
||||
|
||||
/* Resume the module's callback thread, already created in the manager. */
|
||||
_txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
|
||||
}
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has been entered! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call current thread's entry function. */
|
||||
(thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
|
||||
|
||||
/* Suspend thread with a "completed" state. */
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine again. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has exited! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_txm_module_thread_system_suspend(thread_ptr);
|
||||
|
||||
#ifdef TX_SAFETY_CRITICAL
|
||||
|
||||
/* If we ever get here, raise safety critical exception. */
|
||||
TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
|
||||
#endif
|
||||
}
|
@ -0,0 +1,646 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
IMPORT _tx_thread_current_ptr
|
||||
IMPORT _tx_thread_execute_ptr
|
||||
IMPORT _tx_timer_time_slice
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
IMPORT _tx_execution_thread_enter
|
||||
IMPORT _tx_execution_thread_exit
|
||||
#endif
|
||||
IMPORT _tx_thread_preempt_disable
|
||||
IMPORT _txm_module_manager_memory_fault_handler
|
||||
IMPORT _txm_module_manager_memory_fault_info
|
||||
IMPORT _txm_module_priv
|
||||
IMPORT _txm_module_user_mode_exit
|
||||
|
||||
AREA ||.text||, CODE, READONLY
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-Mx/AC5 */
|
||||
/* 6.2.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* 07-29-2022 Scott Larson Removed the code path to skip */
|
||||
/* MPU reloading, optional */
|
||||
/* default MPU settings, */
|
||||
/* resulting in version 6.1.12 */
|
||||
/* 10-31-2022 Scott Larson Added low power support, */
|
||||
/* fixed label syntax, */
|
||||
/* resulting in version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
// {
|
||||
EXPORT _tx_thread_schedule
|
||||
_tx_thread_schedule
|
||||
|
||||
/* This function should only ever be called on Cortex-M
|
||||
from the first schedule request. Subsequent scheduling occurs
|
||||
from the PendSV handling routine below. */
|
||||
|
||||
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
|
||||
|
||||
MOV r0, #0 // Build value for TX_FALSE
|
||||
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
STR r0, [r2, #0] // Clear preempt disable flag
|
||||
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #4 // Clear the FPCA bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
#endif
|
||||
|
||||
/* Enable memory fault registers. */
|
||||
LDR r0, =0xE000ED24 // Build SHCSR address
|
||||
LDR r1, =0x70000 // Enable Usage, Bus, and MemManage faults
|
||||
STR r1, [r0] //
|
||||
|
||||
/* Enable interrupts */
|
||||
CPSIE i
|
||||
|
||||
/* Enter the scheduler for the first time. */
|
||||
|
||||
MOV r0, #0x10000000 // Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 // Load NVIC base
|
||||
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
|
||||
DSB // Complete all memory accesses
|
||||
ISB // Flush pipeline
|
||||
|
||||
/* Wait here for the PendSV to take place. */
|
||||
|
||||
__tx_wait_here
|
||||
B __tx_wait_here // Wait for the PendSV to happen
|
||||
// }
|
||||
|
||||
|
||||
/* Memory Exception Handler. */
|
||||
|
||||
EXPORT MemManage_Handler
|
||||
MemManage_Handler
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
LDR r12,=_txm_module_manager_memory_fault_info // Pickup fault info struct
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup the current thread pointer
|
||||
STR r1, [r12, #0] // Save current thread pointer in fault info structure
|
||||
LDR r0, =0xE000ED24 // Build SHCSR address
|
||||
LDR r1, [r0] // Pickup SHCSR
|
||||
STR r1, [r12, #8] // Save SHCSR
|
||||
LDR r0, =0xE000ED28 // Build CFSR address
|
||||
LDR r1, [r0] // Pickup CFSR
|
||||
STR r1, [r12, #12] // Save CFSR
|
||||
LDR r0, =0xE000ED34 // Build MMFAR address
|
||||
LDR r1, [r0] // Pickup MMFAR
|
||||
STR r1, [r12, #16] // Save MMFAR
|
||||
LDR r0, =0xE000ED38 // Build BFAR address
|
||||
LDR r1, [r0] // Pickup BFAR
|
||||
STR r1, [r12, #20] // Save BFAR
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
STR r0, [r12, #24] // Save CONTROL
|
||||
MRS r1, PSP // Pickup thread stack pointer
|
||||
STR r1, [r12, #28] // Save thread stack pointer
|
||||
LDR r0, [r1] // Pickup saved r0
|
||||
STR r0, [r12, #32] // Save r0
|
||||
LDR r0, [r1, #4] // Pickup saved r1
|
||||
STR r0, [r12, #36] // Save r1
|
||||
STR r2, [r12, #40] // Save r2
|
||||
STR r3, [r12, #44] // Save r3
|
||||
STR r4, [r12, #48] // Save r4
|
||||
STR r5, [r12, #52] // Save r5
|
||||
STR r6, [r12, #56] // Save r6
|
||||
STR r7, [r12, #60] // Save r7
|
||||
STR r8, [r12, #64] // Save r8
|
||||
STR r9, [r12, #68] // Save r9
|
||||
STR r10,[r12, #72] // Save r10
|
||||
STR r11,[r12, #76] // Save r11
|
||||
LDR r0, [r1, #16] // Pickup saved r12
|
||||
STR r0, [r12, #80] // Save r12
|
||||
LDR r0, [r1, #20] // Pickup saved lr
|
||||
STR r0, [r12, #84] // Save lr
|
||||
LDR r0, [r1, #24] // Pickup instruction address at point of fault
|
||||
STR r0, [r12, #4] // Save point of fault
|
||||
LDR r0, [r1, #28] // Pickup xPSR
|
||||
STR r0, [r12, #88] // Save xPSR
|
||||
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #1 // Clear the UNPRIV bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
|
||||
LDR r0, =0xE000ED28 // Build the Memory Management Fault Status Register (MMFSR)
|
||||
LDRB r1, [r0] // Pickup the MMFSR, with the following bit definitions:
|
||||
// Bit 0 = 1 -> Instruction address violation
|
||||
// Bit 1 = 1 -> Load/store address violation
|
||||
// Bit 7 = 1 -> MMFAR is valid
|
||||
STRB r1, [r0] // Clear the MMFSR
|
||||
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
CPSID i // Disable interrupts
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
|
||||
MOV r1, #0 // Build NULL value
|
||||
LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
|
||||
STR r1, [r0] // Clear current thread pointer
|
||||
|
||||
// Return from MemManage_Handler exception
|
||||
LDR r0, =0xE000ED04 // Load ICSR
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
|
||||
/* Generic context PendSV handler. */
|
||||
|
||||
EXPORT PendSV_Handler
|
||||
EXPORT __tx_PendSVHandler
|
||||
PendSV_Handler
|
||||
__tx_PendSVHandler
|
||||
|
||||
/* Get current thread value and new thread pointer. */
|
||||
|
||||
__tx_ts_handler
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
PUSH {r0, lr} // Save LR (and r0 just for alignment)
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
POP {r0, lr} // Recover LR
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
#endif /* EXECUTION PROFILE */
|
||||
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
|
||||
MOV r3, #0 // Build NULL value
|
||||
LDR r1, [r0] // Pickup current thread pointer
|
||||
|
||||
/* Determine if there is a current thread to finish preserving. */
|
||||
|
||||
CBZ r1, __tx_ts_new // If NULL, skip preservation
|
||||
|
||||
/* Recover PSP and preserve current thread context. */
|
||||
|
||||
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
|
||||
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
|
||||
STMDB r12!, {r4-r11} // Save its remaining registers
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_save
|
||||
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
|
||||
_skip_vfp_save
|
||||
#endif
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
STMDB r12!, {LR} // Save LR on the stack
|
||||
|
||||
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
|
||||
|
||||
LDR r5, [r4] // Pickup current time-slice
|
||||
STR r12, [r1, #8] // Save the thread stack pointer
|
||||
CBZ r5, __tx_ts_new // If not active, skip processing
|
||||
|
||||
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
|
||||
|
||||
STR r5, [r1, #24] // Save current time-slice
|
||||
|
||||
/* Clear the global time-slice. */
|
||||
|
||||
STR r3, [r4] // Clear time-slice
|
||||
|
||||
/* Executing thread is now completely preserved!!! */
|
||||
|
||||
__tx_ts_new
|
||||
|
||||
/* Now we are looking for a new thread to execute! */
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Is there another thread ready to execute?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
|
||||
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
|
||||
are disabled to allow use of WFI for waiting for a thread to arrive. */
|
||||
|
||||
__tx_ts_wait
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Pickup the next thread to execute pointer
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_enter // Possibly enter low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB // Ensure no outstanding memory transactions
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#endif
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_exit // Exit low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
B __tx_ts_wait // Loop to continue waiting
|
||||
|
||||
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
|
||||
already in the handler! */
|
||||
|
||||
__tx_ts_ready
|
||||
MOV r7, #0x08000000 // Build clear PendSV value
|
||||
MOV r8, #0xE000E000 // Build base NVIC address
|
||||
STR r7, [r8, #0xD04] // Clear any PendSV
|
||||
|
||||
__tx_ts_restore
|
||||
|
||||
/* A thread is ready, make the current thread the new thread
|
||||
and enable interrupts. */
|
||||
|
||||
STR r1, [r0] // Setup the current thread pointer to the new thread
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
|
||||
/* Increment the thread run count. */
|
||||
|
||||
LDR r7, [r1, #4] // Pickup the current thread run count
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
LDR r5, [r1, #24] // Pickup thread's current time-slice
|
||||
ADD r7, r7, #1 // Increment the thread run count
|
||||
STR r7, [r1, #4] // Store the new run count
|
||||
|
||||
/* Setup global time-slice with thread's current time-slice. */
|
||||
|
||||
STR r5, [r4] // Setup global time-slice
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
PUSH {r0, r1} // Save r0 and r1
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
POP {r0, r1} // Recover r0 and r1
|
||||
#endif
|
||||
|
||||
/* Restore the thread context and PSP. */
|
||||
|
||||
LDR r12, [r1, #8] // Pickup thread's stack pointer
|
||||
|
||||
MRS r5, CONTROL // Pickup current CONTROL register
|
||||
LDR r4, [r1, #0x98] // Pickup current user mode flag
|
||||
BIC r5, r5, #1 // Clear the UNPRIV bit
|
||||
ORR r4, r4, r5 // Build new CONTROL register
|
||||
MSR CONTROL, r4 // Setup new CONTROL register
|
||||
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r3, #0 // Build disable value
|
||||
CPSID i // Disable interrupts
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
#ifdef TXM_MODULE_MPU_DEFAULT
|
||||
CBZ r0, default_mpu // Is this thread owned by a module? No, default MPU setup
|
||||
#else
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
#endif
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
#ifdef TXM_MODULE_MPU_DEFAULT
|
||||
CBZ r2, default_mpu // Is protection required for this module? No, default MPU setup
|
||||
#else
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
#endif
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
|
||||
#ifdef TXM_MODULE_MPU_DEFAULT
|
||||
B config_mpu // configure MPU for module
|
||||
default_mpu
|
||||
LDR r0, =txm_module_default_mpu_registers // default MPU configuration
|
||||
#endif
|
||||
|
||||
config_mpu
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
// Regions 12-15 are reserved for the user to define.
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#endif
|
||||
_tx_enable_mpu
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
skip_mpu_setup
|
||||
CPSIE i // Enable interrupts
|
||||
LDMIA r12!, {LR} // Pickup LR
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_restore // If not, skip VFP restore
|
||||
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
|
||||
_skip_vfp_restore
|
||||
#endif
|
||||
LDMIA r12!, {r4-r11} // Recover thread's registers
|
||||
MSR PSP, r12 // Setup the thread's stack pointer
|
||||
|
||||
/* Return to thread. */
|
||||
|
||||
BX lr // Return to thread!
|
||||
|
||||
|
||||
/* SVC Handler. */
|
||||
|
||||
EXPORT SVC_Handler
|
||||
EXPORT __tx_SVCallHandler
|
||||
SVC_Handler
|
||||
__tx_SVCallHandler
|
||||
MRS r0, PSP // Pickup the PSP stack
|
||||
LDR r1, [r0, #24] // Pickup the point of interrupt
|
||||
LDRB r2, [r1, #-2] // Pickup the SVC parameter
|
||||
|
||||
/* Determine which SVC trap we are processing */
|
||||
|
||||
CMP r2, #1 // Is it the entry into ThreadX?
|
||||
BNE _tx_thread_user_return // No, return to user mode
|
||||
|
||||
/* At this point we have an SVC 1, which means we are entering
|
||||
the kernel from a module thread with user mode selected. */
|
||||
|
||||
LDR r2, =_txm_module_priv // Load address of where we should have come from
|
||||
SUB r2, r2, #1 // Subtract 1 because of THUMB mode.
|
||||
CMP r1, r2 // Did we come from user_mode_entry?
|
||||
IT NE // If no (not equal), then...
|
||||
BXNE lr // return from where we came.
|
||||
|
||||
LDR r3, [r0, #20] // This is the saved LR
|
||||
LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, [r1] // Pickup current thread pointer
|
||||
MOV r1, #0 // Build clear value
|
||||
STR r1, [r2, #0x98] // Clear the current user mode selection for thread
|
||||
STR r3, [r2, #0xA0] // Save the original LR in thread control block
|
||||
|
||||
/* If there is memory protection, use kernel stack */
|
||||
LDR r0, [r2, #0x90] // Load the module instance ptr
|
||||
LDR r0, [r0, #0x0C] // Load the module property flags
|
||||
TST r0, #2 // Check if memory protected
|
||||
BEQ _tx_skip_kernel_stack_enter
|
||||
|
||||
/* Switch to the module thread's kernel stack */
|
||||
LDR r0, [r2, #0xA8] // Load the module kernel stack end
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r1, [r2, #0xA4] // Load the module kernel stack start
|
||||
LDR r3, [r2, #0xAC] // Load the module kernel stack size
|
||||
STR r1, [r2, #12] // Set stack start
|
||||
STR r0, [r2, #16] // Set stack end
|
||||
STR r3, [r2, #20] // Set stack size
|
||||
#endif
|
||||
|
||||
MRS r3, PSP // Pickup thread stack pointer
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
TST lr, #0x10 // Test for extended module stack
|
||||
ITT EQ
|
||||
ORREQ r3, r3, #1 // If so, set LSB in thread stack pointer to indicate extended frame
|
||||
ORREQ lr, lr, #0x10 // Set bit, return with standard frame
|
||||
#endif
|
||||
STR r3, [r2, #0xB0] // Save thread stack pointer
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
BIC r3, #1 // Clear possibly OR'd bit
|
||||
#endif
|
||||
|
||||
/* Build kernel stack by copying thread stack two registers at a time */
|
||||
ADD r3, r3, #32 // Start at bottom of hardware stack
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
|
||||
MSR PSP, r0 // Set kernel stack pointer
|
||||
|
||||
_tx_skip_kernel_stack_enter
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #1 // Clear the UNPRIV bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
BX lr // Return to thread
|
||||
|
||||
_tx_thread_user_return
|
||||
LDR r2, =_txm_module_user_mode_exit // Load address of where we should have come from
|
||||
SUB r2, r2, #1 // Subtract 1 because of THUMB mode.
|
||||
CMP r1, r2 // Did we come from user_mode_exit?
|
||||
IT NE // If no (not equal), then...
|
||||
BXNE lr // return from where we came
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, [r1] // Pickup current thread pointer
|
||||
LDR r1, [r2, #0x9C] // Pick up user mode
|
||||
STR r1, [r2, #0x98] // Set the current user mode selection for thread
|
||||
|
||||
/* If there is memory protection, use kernel stack */
|
||||
LDR r0, [r2, #0x90] // Load the module instance ptr
|
||||
LDR r0, [r0, #0x0C] // Load the module property flags
|
||||
TST r0, #2 // Check if memory protected
|
||||
BEQ _tx_skip_kernel_stack_exit
|
||||
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r0, [r2, #0xB4] // Load the module thread stack start
|
||||
LDR r1, [r2, #0xB8] // Load the module thread stack end
|
||||
LDR r3, [r2, #0xBC] // Load the module thread stack size
|
||||
STR r0, [r2, #12] // Set stack start
|
||||
STR r1, [r2, #16] // Set stack end
|
||||
STR r3, [r2, #20] // Set stack size
|
||||
#endif
|
||||
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
/* If lazy stacking is pending, check if it can be cleared.
|
||||
if(LSPACT && tx_thread_module_stack_start < FPCAR && FPCAR < tx_thread_module_stack_end)
|
||||
then clear LSPACT. */
|
||||
LDR r3, =0xE000EF34 // Address of FPCCR
|
||||
LDR r3, [r3] // Load FPCCR
|
||||
TST r3, #1 // Check if LSPACT is set
|
||||
BEQ _tx_no_lazy_clear // if clear, move on
|
||||
LDR r1, =0xE000EF38 // Address of FPCAR
|
||||
LDR r1, [r1] // Load FPCAR
|
||||
LDR r0, [r2, #0xA4] // Load kernel stack start
|
||||
CMP r1, r0 // If FPCAR < start, move on
|
||||
BLO _tx_no_lazy_clear
|
||||
LDR r0, [r2, #0xA8] // Load kernel stack end
|
||||
CMP r0, r1 // If end < FPCAR, move on
|
||||
BLO _tx_no_lazy_clear
|
||||
BIC r3, #1 // Clear LSPACT
|
||||
LDR r1, =0xE000EF34 // Address of FPCCR
|
||||
STR r3, [r1] // Save updated FPCCR
|
||||
_tx_no_lazy_clear
|
||||
#endif
|
||||
|
||||
LDR r0, [r2, #0xB0] // Load the module thread stack pointer
|
||||
MRS r3, PSP // Pickup kernel stack pointer
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
TST r0, #1 // Is module stack extended?
|
||||
ITTE NE // If so...
|
||||
BICNE lr, #0x10 // Clear bit, return with extended frame
|
||||
BICNE r0, #1 // Clear bit that indicates extended module frame
|
||||
ORREQ lr, lr, #0x10 // Else set bit, return with standard frame
|
||||
#endif
|
||||
|
||||
/* Copy kernel hardware stack to module thread stack. */
|
||||
LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r0, r1 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r2, r3 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r12, lr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r12, lr into thread stack
|
||||
LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
|
||||
SUB r0, r0, #32 // Subtract 32 to get back to top of stack
|
||||
MSR PSP, r0 // Set thread stack pointer
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, [r1] // Pickup current thread pointer
|
||||
LDR r1, [r2, #0x9C] // Pick up user mode
|
||||
|
||||
_tx_skip_kernel_stack_exit
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
ORR r0, r0, r1 // OR in the user mode bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
BX lr // Return to thread
|
||||
|
||||
#ifdef __TARGET_FPU_VFP
|
||||
EXPORT tx_thread_fpu_enable
|
||||
tx_thread_fpu_enable
|
||||
EXPORT tx_thread_fpu_disable
|
||||
tx_thread_fpu_disable
|
||||
|
||||
/* Automatic VPF logic is supported, this function is present only for
|
||||
backward compatibility purposes and therefore simply returns. */
|
||||
|
||||
BX LR // Return to caller
|
||||
|
||||
EXPORT _tx_vfp_access
|
||||
_tx_vfp_access
|
||||
VMOV.F32 s0, s0 // Simply access the VFP
|
||||
BX lr // Return to caller
|
||||
|
||||
#endif
|
||||
|
||||
ALIGN 4
|
||||
END
|
@ -0,0 +1,138 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
AREA ||.text||, CODE, READONLY
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_stack_build Cortex-Mx/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread */
|
||||
/* function_ptr Pointer to shell function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
|
||||
// {
|
||||
EXPORT _txm_module_manager_thread_stack_build
|
||||
_txm_module_manager_thread_stack_build
|
||||
|
||||
/* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
on the Cortex-M should look like the following after it is built:
|
||||
|
||||
Stack Top:
|
||||
lr Interrupted lr (lr at time of PENDSV)
|
||||
r4 Initial value for r4
|
||||
r5 Initial value for r5
|
||||
r6 Initial value for r6
|
||||
r7 Initial value for r7
|
||||
r8 Initial value for r8
|
||||
r9 Initial value for r9
|
||||
r10 Initial value for r10
|
||||
r11 Initial value for r11
|
||||
r0 Initial value for r0 (Hardware stack starts here!!)
|
||||
r1 Initial value for r1
|
||||
r2 Initial value for r2
|
||||
r3 Initial value for r3
|
||||
r12 Initial value for r12
|
||||
lr Initial value for lr
|
||||
pc Initial value for pc
|
||||
xPSR Initial value for xPSR
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR r2, [r0, #16] // Pickup end of stack area
|
||||
BIC r2, r2, #0x7 // Align frame
|
||||
SUB r2, r2, #68 // Subtract frame size
|
||||
LDR r3, =0xFFFFFFFD // Build initial LR value
|
||||
STR r3, [r2, #0] // Save on the stack
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #4] // Store initial r4
|
||||
STR r3, [r2, #8] // Store initial r5
|
||||
STR r3, [r2, #12] // Store initial r6
|
||||
STR r3, [r2, #16] // Store initial r7
|
||||
STR r3, [r2, #20] // Store initial r8
|
||||
STR r3, [r2, #28] // Store initial r10
|
||||
STR r3, [r2, #32] // Store initial r11
|
||||
|
||||
/* Hardware stack follows. */
|
||||
|
||||
STR r0, [r2, #36] // Store initial r0, which is the thread control block
|
||||
|
||||
LDR r3, [r0, #8] // Pickup thread entry info pointer,which is in the stack pointer position of the thread control block.
|
||||
// It was setup in the txm_module_manager_thread_create function. It will be overwritten later in this
|
||||
// function with the actual, initial stack pointer.
|
||||
STR r3, [r2, #40] // Store initial r1, which is the module entry information.
|
||||
LDR r3, [r3, #8] // Pickup data base register from the module information
|
||||
STR r3, [r2, #24] // Store initial r9 (data base register)
|
||||
MOV r3, #0 // Clear r3 again
|
||||
|
||||
STR r3, [r2, #44] // Store initial r2
|
||||
STR r3, [r2, #48] // Store initial r3
|
||||
STR r3, [r2, #52] // Store initial r12
|
||||
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
|
||||
STR r3, [r2, #56] // Store initial lr
|
||||
STR r1, [r2, #60] // Store initial pc
|
||||
MOV r3, #0x01000000 // Only T-bit need be set
|
||||
STR r3, [r2, #64] // Store initial xPSR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
// thread_ptr -> tx_thread_stack_ptr = r2;
|
||||
|
||||
STR r2, [r0, #8] // Save stack pointer in thread's control block
|
||||
BX lr // Return to caller
|
||||
// }
|
||||
END
|
@ -0,0 +1,88 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
IMPORT _txm_module_manager_kernel_dispatch
|
||||
IMPORT _tx_thread_current_ptr
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=5
|
||||
THUMB
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_user_mode_entry Cortex-Mx/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function allows modules to enter kernel mode. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* SVC 1 Enter kernel mode */
|
||||
/* SVC 2 Exit kernel mode */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Modules in user mode */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _txm_module_manager_user_mode_entry(VOID)
|
||||
// {
|
||||
EXPORT _txm_module_manager_user_mode_entry
|
||||
_txm_module_manager_user_mode_entry
|
||||
SVC 1 // Enter kernel
|
||||
EXPORT _txm_module_priv
|
||||
_txm_module_priv
|
||||
// At this point, we are out of user mode. The original LR has been saved in the
|
||||
// thread control block. Simply call the kernel dispatch function.
|
||||
BL _txm_module_manager_kernel_dispatch
|
||||
|
||||
// Pickup the original LR value while still in privileged mode
|
||||
LDR r2, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r3, [r2] // Pickup current thread pointer
|
||||
LDR lr, [r3, #0xA0] // Pickup saved LR from original call
|
||||
|
||||
SVC 2 // Exit kernel and return to user mode
|
||||
EXPORT _txm_module_user_mode_exit
|
||||
_txm_module_user_mode_exit
|
||||
BX lr // Return to the caller
|
||||
// }
|
||||
ALIGN 32
|
||||
END
|
@ -0,0 +1,91 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.global __use_two_region_memory
|
||||
.global __scatterload
|
||||
|
||||
.eabi_attribute Tag_ABI_PCS_RO_data, 1
|
||||
.eabi_attribute Tag_ABI_PCS_R9_use, 1
|
||||
.eabi_attribute Tag_ABI_PCS_RW_data, 2
|
||||
|
||||
.text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_initialize Cortex-Mx/AC6 */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the module c runtime. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* __scatterload Initialize C runtime */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Start module thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Modified comments and made */
|
||||
/* heap user configurable, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _txm_module_initialize(VOID)
|
||||
.global _txm_module_initialize
|
||||
.thumb_func
|
||||
_txm_module_initialize:
|
||||
PUSH {r0-r12,lr} // Save dregs and LR
|
||||
B __scatterload // Call ARM func to initialize variables
|
||||
|
||||
// Override the __rt_exit function.
|
||||
.global __rt_exit
|
||||
.thumb_func
|
||||
__rt_exit:
|
||||
POP {r4-r12,lr} // Restore dregs and LR
|
||||
BX lr // Return to caller
|
||||
|
||||
.global __rt_entry
|
||||
.type __rt_entry, %function
|
||||
__rt_entry:
|
||||
POP {r0-r1}
|
||||
BL __rt_lib_init
|
||||
POP {r2-r12,lr} // Restore dregs and LR
|
||||
BX lr // Return to caller
|
@ -0,0 +1,178 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TXM_MODULE
|
||||
#define TXM_MODULE
|
||||
#endif
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define TX_SOURCE_CODE
|
||||
#endif
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "txm_module.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/* Define the global module entry pointer from the start thread of the module. */
|
||||
|
||||
TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
|
||||
|
||||
|
||||
/* Define the dispatch function pointer used in the module implementation. */
|
||||
|
||||
ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
|
||||
|
||||
|
||||
/* Define the module's heap and align it to 8 bytes. */
|
||||
__attribute__((aligned(8))) UCHAR txm_heap[TXM_MODULE_HEAP_SIZE];
|
||||
|
||||
|
||||
/* Use our asm routine that calls the ARM code to initialize data and heap. */
|
||||
extern VOID _txm_module_initialize(VOID *heap_base, VOID *heap_top);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Cortex-Mx/AC6 */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calls the specified entry function of the thread. It */
|
||||
/* also provides a place for the thread's entry function to return. */
|
||||
/* If the thread returns, this function places the thread in a */
|
||||
/* "COMPLETED" state. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to current thread */
|
||||
/* thread_info Pointer to thread entry info */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_initialize cstartup initialization */
|
||||
/* thread_entry Thread's entry function */
|
||||
/* tx_thread_resume Resume the module callback thread */
|
||||
/* _txm_module_thread_system_suspend Module thread suspension routine */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Initial thread stack frame */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Modified comments and made */
|
||||
/* heap user configurable, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*entry_exit_notify)(TX_THREAD *, UINT);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine if this is the start thread. If so, we must prepare the module for
|
||||
execution. If not, simply skip the C startup code. */
|
||||
if (thread_info -> txm_module_thread_entry_info_start_thread)
|
||||
{
|
||||
/* Initialize the C environment. */
|
||||
_txm_module_initialize(&txm_heap[0], &txm_heap[TXM_MODULE_HEAP_SIZE-1]);
|
||||
|
||||
/* Save the entry info pointer, for later use. */
|
||||
_txm_module_entry_info = thread_info;
|
||||
|
||||
/* Save the kernel function dispatch address. This is used to make all resident calls from
|
||||
the module. */
|
||||
_txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
|
||||
|
||||
/* Ensure that we have a valid pointer. */
|
||||
while (!_txm_module_kernel_call_dispatcher)
|
||||
{
|
||||
/* Loop here, if an error is present getting the dispatch function pointer!
|
||||
An error here typically indicates the resident portion of _tx_thread_schedule
|
||||
is not supporting the trap to obtain the function pointer. */
|
||||
}
|
||||
|
||||
/* Resume the module's callback thread, already created in the manager. */
|
||||
_txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
|
||||
}
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has been entered! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call current thread's entry function. */
|
||||
(thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
|
||||
|
||||
/* Suspend thread with a "completed" state. */
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine again. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has exited! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_txm_module_thread_system_suspend(thread_ptr);
|
||||
|
||||
#ifdef TX_SAFETY_CRITICAL
|
||||
|
||||
/* If we ever get here, raise safety critical exception. */
|
||||
TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
|
||||
#endif
|
||||
}
|
@ -0,0 +1,686 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_thread_execute_ptr
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_thread_preempt_disable
|
||||
.global _txm_module_manager_memory_fault_handler
|
||||
.global _txm_module_manager_memory_fault_info
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
.global _tx_execution_thread_enter
|
||||
.global _tx_execution_thread_exit
|
||||
#endif
|
||||
#ifdef TX_LOW_POWER
|
||||
.global tx_low_power_enter
|
||||
.global tx_low_power_exit
|
||||
#endif
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-Mx/AC6 */
|
||||
/* 6.2.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* 07-29-2022 Scott Larson Removed the code path to skip */
|
||||
/* MPU reloading, optional */
|
||||
/* default MPU settings, */
|
||||
/* resulting in version 6.1.12 */
|
||||
/* 10-31-2022 Scott Larson Added low power support, */
|
||||
/* resulting in version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
// {
|
||||
.global _tx_thread_schedule
|
||||
.thumb_func
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* This function should only ever be called on Cortex-M
|
||||
from the first schedule request. Subsequent scheduling occurs
|
||||
from the PendSV handling routine below. */
|
||||
|
||||
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
|
||||
|
||||
MOV r0, #0 // Build value for TX_FALSE
|
||||
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
STR r0, [r2, #0] // Clear preempt disable flag
|
||||
|
||||
#ifdef __ARM_FP
|
||||
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #4 // Clear the FPCA bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
#endif
|
||||
|
||||
/* Enable memory fault registers. */
|
||||
LDR r0, =0xE000ED24 // Build SHCSR address
|
||||
LDR r1, =0x70000 // Enable Usage, Bus, and MemManage faults
|
||||
STR r1, [r0] //
|
||||
|
||||
/* Enable interrupts */
|
||||
CPSIE i
|
||||
|
||||
/* Enter the scheduler for the first time. */
|
||||
|
||||
MOV r0, #0x10000000 // Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 // Load NVIC base
|
||||
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
|
||||
DSB // Complete all memory accesses
|
||||
ISB // Flush pipeline
|
||||
|
||||
/* Wait here for the PendSV to take place. */
|
||||
|
||||
__tx_wait_here:
|
||||
B __tx_wait_here // Wait for the PendSV to happen
|
||||
// }
|
||||
|
||||
|
||||
/* Memory Exception Handler. */
|
||||
.global MemManage_Handler
|
||||
.global BusFault_Handler
|
||||
.global UsageFault_Handler
|
||||
.thumb_func
|
||||
MemManage_Handler:
|
||||
.thumb_func
|
||||
BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
LDR r12,=_txm_module_manager_memory_fault_info // Pickup fault info struct
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup the current thread pointer
|
||||
STR r1, [r12, #0] // Save current thread pointer in fault info structure
|
||||
LDR r0, =0xE000ED24 // Build SHCSR address
|
||||
LDR r1, [r0] // Pickup SHCSR
|
||||
STR r1, [r12, #8] // Save SHCSR
|
||||
LDR r0, =0xE000ED28 // Build CFSR address
|
||||
LDR r1, [r0] // Pickup CFSR
|
||||
STR r1, [r12, #12] // Save CFSR
|
||||
LDR r0, =0xE000ED34 // Build MMFAR address
|
||||
LDR r1, [r0] // Pickup MMFAR
|
||||
STR r1, [r12, #16] // Save MMFAR
|
||||
LDR r0, =0xE000ED38 // Build BFAR address
|
||||
LDR r1, [r0] // Pickup BFAR
|
||||
STR r1, [r12, #20] // Save BFAR
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
STR r0, [r12, #24] // Save CONTROL
|
||||
MRS r1, PSP // Pickup thread stack pointer
|
||||
STR r1, [r12, #28] // Save thread stack pointer
|
||||
LDR r0, [r1] // Pickup saved r0
|
||||
STR r0, [r12, #32] // Save r0
|
||||
LDR r0, [r1, #4] // Pickup saved r1
|
||||
STR r0, [r12, #36] // Save r1
|
||||
STR r2, [r12, #40] // Save r2
|
||||
STR r3, [r12, #44] // Save r3
|
||||
STR r4, [r12, #48] // Save r4
|
||||
STR r5, [r12, #52] // Save r5
|
||||
STR r6, [r12, #56] // Save r6
|
||||
STR r7, [r12, #60] // Save r7
|
||||
STR r8, [r12, #64] // Save r8
|
||||
STR r9, [r12, #68] // Save r9
|
||||
STR r10,[r12, #72] // Save r10
|
||||
STR r11,[r12, #76] // Save r11
|
||||
LDR r0, [r1, #16] // Pickup saved r12
|
||||
STR r0, [r12, #80] // Save r12
|
||||
LDR r0, [r1, #20] // Pickup saved lr
|
||||
STR r0, [r12, #84] // Save lr
|
||||
LDR r0, [r1, #24] // Pickup instruction address at point of fault
|
||||
STR r0, [r12, #4] // Save point of fault
|
||||
LDR r0, [r1, #28] // Pickup xPSR
|
||||
STR r0, [r12, #88] // Save xPSR
|
||||
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #1 // Clear the UNPRIV bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
|
||||
LDR r0, =0xE000ED28 // Build the Memory Management Fault Status Register (MMFSR)
|
||||
LDRB r1, [r0] // Pickup the MMFSR, with the following bit definitions:
|
||||
// Bit 0 = 1 -> Instruction address violation
|
||||
// Bit 1 = 1 -> Load/store address violation
|
||||
// Bit 7 = 1 -> MMFAR is valid
|
||||
STRB r1, [r0] // Clear the MMFSR
|
||||
|
||||
#ifdef __ARM_FP
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
CPSID i // Disable interrupts
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
|
||||
MOV r1, #0 // Build NULL value
|
||||
LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
|
||||
STR r1, [r0] // Clear current thread pointer
|
||||
|
||||
// Return from MemManage_Handler exception
|
||||
LDR r0, =0xE000ED04 // Load ICSR
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
|
||||
/* Generic context PendSV handler. */
|
||||
|
||||
.global PendSV_Handler
|
||||
.global __tx_PendSVHandler
|
||||
.syntax unified
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
.thumb_func
|
||||
__tx_PendSVHandler:
|
||||
|
||||
/* Get current thread value and new thread pointer. */
|
||||
|
||||
__tx_ts_handler:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
PUSH {r0, lr} // Save LR (and r0 just for alignment)
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
POP {r0, lr} // Recover LR
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif /* TX_PORT_USE_BASEPRI */
|
||||
#endif /* EXECUTION PROFILE */
|
||||
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
|
||||
MOV r3, #0 // Build NULL value
|
||||
LDR r1, [r0] // Pickup current thread pointer
|
||||
|
||||
/* Determine if there is a current thread to finish preserving. */
|
||||
|
||||
CBZ r1, __tx_ts_new // If NULL, skip preservation
|
||||
|
||||
/* Recover PSP and preserve current thread context. */
|
||||
|
||||
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
|
||||
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
|
||||
STMDB r12!, {r4-r11} // Save its remaining registers
|
||||
#ifdef __ARM_FP
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_save
|
||||
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
|
||||
_skip_vfp_save:
|
||||
#endif
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
STMDB r12!, {LR} // Save LR on the stack
|
||||
|
||||
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
|
||||
|
||||
LDR r5, [r4] // Pickup current time-slice
|
||||
STR r12, [r1, #8] // Save the thread stack pointer
|
||||
CBZ r5, __tx_ts_new // If not active, skip processing
|
||||
|
||||
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
|
||||
|
||||
STR r5, [r1, #24] // Save current time-slice
|
||||
|
||||
/* Clear the global time-slice. */
|
||||
|
||||
STR r3, [r4] // Clear time-slice
|
||||
|
||||
/* Executing thread is now completely preserved!!! */
|
||||
|
||||
__tx_ts_new:
|
||||
|
||||
/* Now we are looking for a new thread to execute! */
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Is there another thread ready to execute?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
|
||||
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
|
||||
are disabled to allow use of WFI for waiting for a thread to arrive. */
|
||||
|
||||
__tx_ts_wait:
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI
|
||||
MSR BASEPRI, r1
|
||||
#else
|
||||
CPSID i // Disable interrupts
|
||||
#endif
|
||||
LDR r1, [r2] // Pickup the next thread to execute pointer
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_enter // Possibly enter low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB // Ensure no outstanding memory transactions
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#endif
|
||||
|
||||
#ifdef TX_LOW_POWER
|
||||
PUSH {r0-r3}
|
||||
BL tx_low_power_exit // Exit low power mode
|
||||
POP {r0-r3}
|
||||
#endif
|
||||
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
B __tx_ts_wait // Loop to continue waiting
|
||||
|
||||
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
|
||||
already in the handler! */
|
||||
|
||||
__tx_ts_ready:
|
||||
MOV r7, #0x08000000 // Build clear PendSV value
|
||||
MOV r8, #0xE000E000 // Build base NVIC address
|
||||
STR r7, [r8, #0xD04] // Clear any PendSV
|
||||
|
||||
__tx_ts_restore:
|
||||
|
||||
/* A thread is ready, make the current thread the new thread
|
||||
and enable interrupts. */
|
||||
|
||||
STR r1, [r0] // Setup the current thread pointer to the new thread
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r4, #0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r4
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
|
||||
/* Increment the thread run count. */
|
||||
|
||||
LDR r7, [r1, #4] // Pickup the current thread run count
|
||||
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
|
||||
LDR r5, [r1, #24] // Pickup thread's current time-slice
|
||||
ADD r7, r7, #1 // Increment the thread run count
|
||||
STR r7, [r1, #4] // Store the new run count
|
||||
|
||||
/* Setup global time-slice with thread's current time-slice. */
|
||||
|
||||
STR r5, [r4] // Setup global time-slice
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
PUSH {r0, r1} // Save r0 and r1
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
POP {r0, r1} // Recover r0 and r1
|
||||
#endif
|
||||
|
||||
/* Restore the thread context and PSP. */
|
||||
|
||||
LDR r12, [r1, #8] // Pickup thread's stack pointer
|
||||
|
||||
MRS r5, CONTROL // Pickup current CONTROL register
|
||||
LDR r4, [r1, #0x98] // Pickup current user mode flag
|
||||
BIC r5, r5, #1 // Clear the UNPRIV bit
|
||||
ORR r4, r4, r5 // Build new CONTROL register
|
||||
MSR CONTROL, r4 // Setup new CONTROL register
|
||||
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r3, #0 // Build disable value
|
||||
CPSID i // Disable interrupts
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
#ifdef TXM_MODULE_MPU_DEFAULT
|
||||
CBZ r0, default_mpu // Is this thread owned by a module? No, default MPU setup
|
||||
#else
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
#endif
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
#ifdef TXM_MODULE_MPU_DEFAULT
|
||||
CBZ r2, default_mpu // Is protection required for this module? No, default MPU setup
|
||||
#else
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
#endif
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
|
||||
#ifdef TXM_MODULE_MPU_DEFAULT
|
||||
B config_mpu // configure MPU for module
|
||||
default_mpu:
|
||||
LDR r0, =txm_module_default_mpu_registers // default MPU configuration
|
||||
#endif
|
||||
|
||||
config_mpu:
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
// Regions 12-15 are reserved for the user to define.
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#endif
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
skip_mpu_setup:
|
||||
CPSIE i // Enable interrupts
|
||||
LDMIA r12!, {LR} // Pickup LR
|
||||
#ifdef __ARM_FP
|
||||
TST LR, #0x10 // Determine if the VFP extended frame is present
|
||||
BNE _skip_vfp_restore // If not, skip VFP restore
|
||||
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
|
||||
_skip_vfp_restore:
|
||||
#endif
|
||||
LDMIA r12!, {r4-r11} // Recover thread's registers
|
||||
MSR PSP, r12 // Setup the thread's stack pointer
|
||||
|
||||
/* Return to thread. */
|
||||
|
||||
BX lr // Return to thread!
|
||||
|
||||
|
||||
/* SVC Handler. */
|
||||
|
||||
.global SVC_Handler
|
||||
.thumb_func
|
||||
SVC_Handler:
|
||||
.global __tx_SVCallHandler
|
||||
.thumb_func
|
||||
__tx_SVCallHandler:
|
||||
|
||||
MRS r0, PSP // Pickup the PSP stack
|
||||
LDR r1, [r0, #24] // Pickup the point of interrupt
|
||||
LDRB r2, [r1, #-2] // Pickup the SVC parameter
|
||||
|
||||
/* Determine which SVC trap we are processing */
|
||||
|
||||
CMP r2, #1 // Is it the entry into ThreadX?
|
||||
BNE _tx_thread_user_return // No, return to user mode
|
||||
|
||||
/* At this point we have an SVC 1, which means we are entering
|
||||
the kernel from a module thread with user mode selected. */
|
||||
|
||||
LDR r2, =_txm_module_priv // Load address of where we should have come from
|
||||
CMP r1, r2 // Did we come from user_mode_entry?
|
||||
IT NE // If no (not equal), then...
|
||||
BXNE lr // return from where we came.
|
||||
|
||||
LDR r3, [r0, #20] // This is the saved LR
|
||||
LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, [r1] // Pickup current thread pointer
|
||||
MOV r1, #0 // Build clear value
|
||||
STR r1, [r2, #0x98] // Clear the current user mode selection for thread
|
||||
STR r3, [r2, #0xA0] // Save the original LR in thread control block
|
||||
|
||||
/* If there is memory protection, use kernel stack */
|
||||
LDR r0, [r2, #0x90] // Load the module instance ptr
|
||||
LDR r0, [r0, #0x0C] // Load the module property flags
|
||||
TST r0, #2 // Check if memory protected
|
||||
BEQ _tx_skip_kernel_stack_enter
|
||||
|
||||
/* Switch to the module thread's kernel stack */
|
||||
LDR r0, [r2, #0xA8] // Load the module kernel stack end
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r1, [r2, #0xA4] // Load the module kernel stack start
|
||||
LDR r3, [r2, #0xAC] // Load the module kernel stack size
|
||||
STR r1, [r2, #12] // Set stack start
|
||||
STR r0, [r2, #16] // Set stack end
|
||||
STR r3, [r2, #20] // Set stack size
|
||||
#endif
|
||||
|
||||
MRS r3, PSP // Pickup thread stack pointer
|
||||
#ifdef __ARM_FP
|
||||
TST lr, #0x10 // Test for extended module stack
|
||||
ITT EQ
|
||||
ORREQ r3, r3, #1 // If so, set LSB in thread stack pointer to indicate extended frame
|
||||
ORREQ lr, lr, #0x10 // Set bit, return with standard frame
|
||||
#endif
|
||||
STR r3, [r2, #0xB0] // Save thread stack pointer
|
||||
#ifdef __ARM_FP
|
||||
BIC r3, #1 // Clear possibly OR'd bit
|
||||
#endif
|
||||
|
||||
/* Build kernel stack by copying thread stack two registers at a time */
|
||||
ADD r3, r3, #32 // Start at bottom of hardware stack
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
LDMDB r3!, {r1-r2}
|
||||
STMDB r0!, {r1-r2}
|
||||
|
||||
MSR PSP, r0 // Set kernel stack pointer
|
||||
|
||||
_tx_skip_kernel_stack_enter:
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
BIC r0, r0, #1 // Clear the UNPRIV bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
BX lr // Return to thread
|
||||
|
||||
_tx_thread_user_return:
|
||||
LDR r2, =_txm_module_user_mode_exit // Load address of where we should have come from
|
||||
CMP r1, r2 // Did we come from user_mode_exit?
|
||||
IT NE // If no (not equal), then...
|
||||
BXNE lr // return from where we came
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, [r1] // Pickup current thread pointer
|
||||
LDR r1, [r2, #0x9C] // Pick up user mode
|
||||
STR r1, [r2, #0x98] // Set the current user mode selection for thread
|
||||
|
||||
/* If there is memory protection, use kernel stack */
|
||||
LDR r0, [r2, #0x90] // Load the module instance ptr
|
||||
LDR r0, [r0, #0x0C] // Load the module property flags
|
||||
TST r0, #2 // Check if memory protected
|
||||
BEQ _tx_skip_kernel_stack_exit
|
||||
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r0, [r2, #0xB4] // Load the module thread stack start
|
||||
LDR r1, [r2, #0xB8] // Load the module thread stack end
|
||||
LDR r3, [r2, #0xBC] // Load the module thread stack size
|
||||
STR r0, [r2, #12] // Set stack start
|
||||
STR r1, [r2, #16] // Set stack end
|
||||
STR r3, [r2, #20] // Set stack size
|
||||
#endif
|
||||
|
||||
#ifdef __ARM_FP
|
||||
/* If lazy stacking is pending, check if it can be cleared.
|
||||
if(LSPACT && tx_thread_module_stack_start < FPCAR && FPCAR < tx_thread_module_stack_end)
|
||||
then clear LSPACT. */
|
||||
LDR r3, =0xE000EF34 // Address of FPCCR
|
||||
LDR r3, [r3] // Load FPCCR
|
||||
TST r3, #1 // Check if LSPACT is set
|
||||
BEQ _tx_no_lazy_clear // if clear, move on
|
||||
LDR r1, =0xE000EF38 // Address of FPCAR
|
||||
LDR r1, [r1] // Load FPCAR
|
||||
LDR r0, [r2, #0xA4] // Load kernel stack start
|
||||
CMP r1, r0 // If FPCAR < start, move on
|
||||
BLO _tx_no_lazy_clear
|
||||
LDR r0, [r2, #0xA8] // Load kernel stack end
|
||||
CMP r0, r1 // If end < FPCAR, move on
|
||||
BLO _tx_no_lazy_clear
|
||||
BIC r3, #1 // Clear LSPACT
|
||||
LDR r1, =0xE000EF34 // Address of FPCCR
|
||||
STR r3, [r1] // Save updated FPCCR
|
||||
_tx_no_lazy_clear:
|
||||
#endif
|
||||
|
||||
LDR r0, [r2, #0xB0] // Load the module thread stack pointer
|
||||
MRS r3, PSP // Pickup kernel stack pointer
|
||||
#ifdef __ARM_FP
|
||||
TST r0, #1 // Is module stack extended?
|
||||
ITTE NE // If so...
|
||||
BICNE lr, #0x10 // Clear bit, return with extended frame
|
||||
BICNE r0, #1 // Clear bit that indicates extended module frame
|
||||
ORREQ lr, lr, #0x10 // Else set bit, return with standard frame
|
||||
#endif
|
||||
|
||||
/* Copy kernel hardware stack to module thread stack. */
|
||||
LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r0, r1 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r2, r3 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r12, lr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r12, lr into thread stack
|
||||
LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
|
||||
SUB r0, r0, #32 // Subtract 32 to get back to top of stack
|
||||
MSR PSP, r0 // Set thread stack pointer
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r2, [r1] // Pickup current thread pointer
|
||||
LDR r1, [r2, #0x9C] // Pick up user mode
|
||||
|
||||
_tx_skip_kernel_stack_exit:
|
||||
MRS r0, CONTROL // Pickup current CONTROL register
|
||||
ORR r0, r0, r1 // OR in the user mode bit
|
||||
MSR CONTROL, r0 // Setup new CONTROL register
|
||||
BX lr // Return to thread
|
||||
|
||||
|
||||
/* Kernel entry function from user mode. */
|
||||
|
||||
.global _txm_module_manager_kernel_dispatch
|
||||
.align 5
|
||||
.syntax unified
|
||||
// VOID _txm_module_manager_user_mode_entry(VOID)
|
||||
// {
|
||||
.global _txm_module_manager_user_mode_entry
|
||||
.thumb_func
|
||||
_txm_module_manager_user_mode_entry:
|
||||
SVC 1 // Enter kernel
|
||||
_txm_module_priv:
|
||||
/* At this point, we are out of user mode. The original LR has been saved in the
|
||||
thread control block. Simply call the kernel dispatch function. */
|
||||
BL _txm_module_manager_kernel_dispatch
|
||||
|
||||
/* Pickup the original LR value while still in privileged mode */
|
||||
LDR r2, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r3, [r2] // Pickup current thread pointer
|
||||
LDR lr, [r3, #0xA0] // Pickup saved LR from original call
|
||||
|
||||
SVC 2 // Exit kernel and return to user mode
|
||||
_txm_module_user_mode_exit:
|
||||
BX lr // Return to the caller
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
// }
|
||||
|
||||
#ifdef __ARM_FP
|
||||
|
||||
.global tx_thread_fpu_enable
|
||||
.thumb_func
|
||||
tx_thread_fpu_enable:
|
||||
.global tx_thread_fpu_disable
|
||||
.thumb_func
|
||||
tx_thread_fpu_disable:
|
||||
|
||||
/* Automatic VPF logic is supported, this function is present only for
|
||||
backward compatibility purposes and therefore simply returns. */
|
||||
|
||||
BX LR // Return to caller
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user