diff --git a/3rd_party/threadx/CONTRIBUTING.md b/3rd_party/threadx/CONTRIBUTING.md new file mode 100644 index 00000000..c282e9a1 --- /dev/null +++ b/3rd_party/threadx/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to +agree to a Contributor License Agreement (CLA) declaring that you have the right to, +and actually do, grant us the rights to use your contribution. For details, visit +https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need +to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the +instructions provided by the bot. You will only need to do this once across all repositories using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file diff --git a/3rd_party/threadx/LICENSE.txt b/3rd_party/threadx/LICENSE.txt new file mode 100644 index 00000000..d41596fc --- /dev/null +++ b/3rd_party/threadx/LICENSE.txt @@ -0,0 +1,246 @@ +MICROSOFT SOFTWARE LICENSE TERMS + +MICROSOFT AZURE RTOS + +Shape + +These license terms are an agreement between you and Microsoft Corporation (or +one of its affiliates). They apply to the software named above and any Microsoft +services or software updates (except to the extent such services or updates are +accompanied by new or additional terms, in which case those different terms +apply prospectively and do not alter your or Microsoft’s rights relating to +pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU +HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. + +1. INSTALLATION AND USE RIGHTS. + +a) General. You may install and use the software and the included Microsoft +applications solely for internal development, testing and evaluation purposes. +Any distribution or production use requires a separate license as set forth in +Section 2. + +b) Contributions. Microsoft welcomes contributions to this software. In the event +that you make a contribution to this software you will be required to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and +actually do, grant Microsoft the rights to use your contribution. For details, +visit https://cla.microsoft.com. + +c) Included Microsoft Applications. The software includes other Microsoft +applications which are governed by the licenses embedded in or made available +with those applications. + +d) Third Party Components. The software may include third party components with +separate legal notices or governed by other agreements, as may be described +within the software or in the ThirdPartyNotices file(s) accompanying the +software. + +e) Competitive Benchmarking. If you are a direct competitor, and you access or use +the software for purposes of competitive benchmarking, analysis, or intelligence +gathering, you waive as against Microsoft, its subsidiaries, and its affiliated +companies (including prospectively) any competitive use, access, and +benchmarking test restrictions in the terms governing your software to the +extent your terms of use are, or purport to be, more restrictive than +Microsoft’s terms. If you do not waive any such purported restrictions in the +terms governing your software, you are not allowed to access or use this +software, and will not do so. + +2. DISTRIBUTION AND PRODUCTION USE. If you have obtained and/or are developing on +microprocessor(s) and/or microcontroller(s) (“hardware”) listed in the file +named “LICENSED-HARDWARE.txt” included in the repository and/or distributed with +the software you have the following rights in and to the software solely when +used in combination with the hardware. In the event hardware is not listed in +the LICENSED-HARDWARE.txt file, you do not have the rights in this Section 2. + +a) Distribution and Production Use Rights. + +i. You may use the software in production (e.g. program the modified or unmodified +software to devices you own or control) and distribute (i.e. make available to +third parties) the modified or unmodified binary image produced from this code. + + +ii. You may permit your device distributors or developers to copy and distribute the +binary image as programmed or to be programmed to your devices. + +iii. You may redistribute the unmodified or modified source to your device +distributors or developers. Modifications must be clearly marked. Any +redistribution in source code form must contain this license and any other +licenses that accompany the software. + +b) Requirements. For any code you distribute, you must: + +i. when distributed in binary form, except as embedded in a device, include with +such distribution the terms of this agreement; + +ii. when distributed in source code form to distributors or developers of your +devices, include with such distribution the terms of this agreement; and + +iii. indemnify, defend and hold harmless Microsoft from any claims, including +attorneys’ fees, related to the distribution or use of your devices, except to +the extent that any claim is based solely on the unmodified software. + +c) Restrictions. You may not: + +i. use or modify the software to create a competing real time operating system +software; + +ii. remove any copyright notices or licenses contained in the software; + +iii. use Microsoft’s trademarks or trade dress in your application in any way that +suggests your device or application comes from or is endorsed by Microsoft; + +iv. transfer individual components, specific libraries, classes, functions or code +fragments of the software separately for purposes unrelated to the software; or + +v. use or distribute the software in any way that would subject the software or +Microsoft’s intellectual property or technology to any other license terms. + +3. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all +other rights. Unless applicable law gives you more rights despite this +limitation, you will not (and have no right to): + +a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in +the software; + +b) use the software in any way that is against the law or to create or propagate +malware; or + +c) share, publish, distribute, or lease the software (except as permitted in +Section 2 above), or provide the software as a stand-alone offering for others +to use. + +4. DATA. This software may interact with other Microsoft products that collect data +that is transmitted to Microsoft. To learn more about how Microsoft processes +personal data we collect, please see the Microsoft Privacy Statement at +https://go.microsoft.com/fwlink/?LinkId=248681. + +5. EXPORT RESTRICTIONS. You must comply with all domestic and international export +laws and regulations that apply to the software, which include restrictions on +destinations, end users, and end use. For further information on export +restrictions, visit https://aka.ms/exporting. + +6. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any +support services for the software. Any support provided is “as is”, “with all +faults”, and without warranty of any kind. + +7. UPDATES. Microsoft may periodically update the software. You may obtain updates +only from Microsoft or Microsoft-authorized sources. Updates may not include or +support all existing software features, services, or peripheral devices. + +8. TERMINATION. Without prejudice to any other rights, Microsoft may terminate this +agreement if you fail to comply with any of its terms or conditions. In such +event, you must destroy all copies of the software and all of its component +parts. + +9. ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for +supplements, updates, or third-party applications, is the entire agreement for +the software. To the extent you have entered into a separate agreement with +Microsoft relating specifically to the software, the terms in such agreement +shall control. + +10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in +the United States or Canada, the laws of the state or province where you live +(or, if a business, where your principal place of business is located) govern +the interpretation of this agreement, claims for its breach, and all other +claims (including consumer protection, unfair competition, and tort claims), +regardless of conflict of laws principles. If you acquired the software in any +other country, its laws apply. If U.S. federal jurisdiction exists, you and +Microsoft consent to exclusive jurisdiction and venue in the federal court in +King County, Washington for all disputes heard in court. If not, you and +Microsoft consent to exclusive jurisdiction and venue in the Superior Court of +King County, Washington for all disputes heard in court. + +11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal +rights. You may have other rights, including consumer rights, under the laws of +your state or country. Separate and apart from your relationship with Microsoft, +you may also have rights with respect to the party from which you acquired the +software. This agreement does not change those other rights if the laws of your +state or country do not permit it to do so. For example, if you acquired the +software in one of the below regions, or mandatory country law applies, then the +following provisions apply to you: + +a) Australia. You have statutory guarantees under the Australian Consumer Law and +nothing in this agreement is intended to affect those rights. + +b) Germany and Austria. + +i. Warranty. The properly licensed software will perform substantially as +described in any Microsoft materials that accompany the software. However, +Microsoft gives no contractual guarantee in relation to the licensed software. + +ii. Limitation of Liability. In case of intentional conduct, gross negligence, +claims based on the Product Liability Act, as well as, in case of death or +personal or physical injury, Microsoft is liable according to the statutory law. + + +Subject to the foregoing clause ii., Microsoft will only be liable for slight +negligence if Microsoft is in breach of such material contractual obligations, +the fulfillment of which facilitate the due performance of this agreement, the +breach of which would endanger the purpose of this agreement and the compliance +with which a party may constantly trust in (so-called "cardinal obligations"). +In other cases of slight negligence, Microsoft will not be liable for slight +negligence. + +12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF +USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO +THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED +WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. + +13. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING +DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM +MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT +RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, +INDIRECT, OR INCIDENTAL DAMAGES. + +This limitation applies to (a) anything related to the software, services, +content (including code) on third party Internet sites, or third party +applications; and (b) claims for breach of contract, warranty, guarantee, or +condition; strict liability, negligence, or other tort; or any other claim; in +each case to the extent permitted by applicable law. + +It also applies even if Microsoft knew or should have known about the +possibility of the damages. The above limitation or exclusion may not apply to +you because your state, province, or country may not allow the exclusion or +limitation of incidental, consequential, or other damages. + + + +Please note: As this software is distributed in Canada, some of the clauses in +this agreement are provided below in French. + +Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce +contrat sont fournies ci-dessous en français. + +EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel +». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft +n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits +additionnels en vertu du droit local sur la protection des consommateurs, que ce +contrat ne peut modifier. La ou elles sont permises par le droit locale, les +garanties implicites de qualité marchande, d’adéquation à un usage particulier +et d’absence de contrefaçon sont exclues. + +LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES +DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une +indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous +ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris +les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. + +Cette limitation concerne: + +•tout ce qui est relié au logiciel, aux services ou au contenu (y compris le +code) figurant sur des sites Internet tiers ou dans des programmes tiers; et + +•les réclamations au titre de violation de contrat ou de garantie, ou au titre +de responsabilité stricte, de négligence ou d’une autre faute dans la limite +autorisée par la loi en vigueur. + +Elle s’applique également, même si Microsoft connaissait ou devrait connaître +l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la +limitation de responsabilité pour les dommages indirects, accessoires ou de +quelque nature que ce soit, il se peut que la limitation ou l’exclusion +ci-dessus ne s’appliquera pas à votre égard. + +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous +pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent +contrat ne modifie pas les droits que vous confèrent les lois de votre pays si +celles-ci ne le permettent pas. \ No newline at end of file diff --git a/3rd_party/threadx/LICENSED-HARDWARE.txt b/3rd_party/threadx/LICENSED-HARDWARE.txt new file mode 100644 index 00000000..006731c6 --- /dev/null +++ b/3rd_party/threadx/LICENSED-HARDWARE.txt @@ -0,0 +1,45 @@ +LICENSED HARDWARE LIST + +Last Updated: 2021-04-01 + +Microsoft has entered into OEM Agreements with manufacturers of the following +microprocessors and microcontrollers (the “hardware”) to enable those +manufacturers to include and distribute Azure RTOS in certain hardware. If you +have obtained and/or are developing on microprocessor(s) and/or +microcontroller(s) (“hardware”) listed below you inherit the “Distribution and +Production Use” rights in Section 2 of the Microsoft Software License Terms for +Microsoft Azure RTOS. If hardware is not listed below, you do not have those +rights. + + +STMicroelectronics: + + STM32 MCUs + STM32 MPUs + +MediaTek: + + MT3620 MCU (Azure Sphere) + +Microchip: + + PIC 32-bit MCUs + SAM 32-bit MCUs + SAM 32-bit MPUs + +NXP: + + i.MX RT10xx and RT116x/7x series crossover MCUs + LPC5500 series + + +Renesas: + + Synergy Platform + RX Family of MCUs + RA Family of MCUs + RZ Family of MPUs + +-------------------------------------------------------------------------------- + +More coming soon. Please check back frequently for updates. diff --git a/3rd_party/threadx/README.md b/3rd_party/threadx/README.md new file mode 100644 index 00000000..92f79ff9 --- /dev/null +++ b/3rd_party/threadx/README.md @@ -0,0 +1,111 @@ +![cortex_m0](https://github.com/azure-rtos/threadx/workflows/cortex_m0/badge.svg) +![cortex_m3](https://github.com/azure-rtos/threadx/workflows/cortex_m3/badge.svg) +![cortex_m4](https://github.com/azure-rtos/threadx/workflows/cortex_m4/badge.svg) +![cortex_m7](https://github.com/azure-rtos/threadx/workflows/cortex_m7/badge.svg) + +# Azure RTOS ThreadX + +This advanced real-time operating system (RTOS) is designed specifically for deeply embedded applications. Among the multiple benefits it provides are advanced scheduling facilities, message passing, interrupt management, and messaging services. Azure RTOS ThreadX has many advanced features, including picokernel architecture, preemption threshold, event chaining, and a rich set of system services. + +## Documentation + +Documentation for this library can be found here: http://docs.microsoft.com/azure/rtos/threadx + + +# Understanding inter-component dependencies + +The main components of Azure RTOS are each provided in their own repository, but there are dependencies between them--shown in the following graph--that are important to understand when setting up your builds. + +![dependency graph](docs/deps.png) + +# Building and using the library + +## Prerequisites + +Install the following tools: + +* [CMake](https://cmake.org/download/) version 3.0 or later +* [GCC compilers for arm-none-eabi](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) +* [Ninja](https://ninja-build.org/) + +## Cloning the repo + +```bash +$ git clone https://github.com/azure-rtos/threadx.git +``` + +## Building as a static library + +Each component of Azure RTOS comes with a composable CMake-based build system that supports many different MCUs and host systems. Integrating any of these components into your device app code is as simple as adding a git submodule and then including it in your build using the CMake command `add_subdirectory()`. + +While the typical usage pattern is to include threadx into your device code source tree to be built & linked with your code, you can compile this project as a standalone static library to confirm your build is set up correctly. + +```bash +$ cmake -Bbuild -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_m4.cmake -GNinja . + +$ cmake --build ./build +``` + +NOTE: You will have to take the dependency graph above into account when building anything other than threadx itself. + +# Repository Structure and Usage + +## Branches & Releases + +The master branch has the most recent code with all new features and bug fixes. It does not represent the latest General Availability (GA) release of the library. + +## Releases + +Each official release (preview or GA) will be tagged to mark the commit and push it into the Github releases tab, e.g. `v6.0-rel`. + +## Directory layout + +``` +- cmake +- common + - inc + - src +- ports + - cortex_m0/gnu + - inc + - src + - cortex_m3/gnu + - inc + - src + - cortex_m4/gnu + - inc + - src + - cortex_m7/gnu + - inc + - src +- samples +``` + +# Security + +Azure RTOS provides OEMs with components to secure communication and to create code and data isolation using underlying MCU/MPU hardware protection mechanisms. It is ultimately the responsibility of the device builder to ensure the device fully meets the evolving security requirements associated with its specific use case. + +# Licensing + +License terms for using Azure RTOS are defined in the LICENSE.txt file of this repo. Please refer to this file for all definitive licensing information. No additional license fees are required for deploying Azure RTOS on hardware defined in the LICENSED-HARDWARE.txt file. If you are using hardware not defined in the LICENSED-HARDWARE.txt file or have licensing questions in general, please contact Microsoft directly at https://azure-rtos.ms-iot-contact.com/ + +# Contribution, feedback, issues, and professional support + +If you encounter any bugs, have suggestions for new features, or if you would like to become an active contributor to this project, please follow the instructions provided in the contribution guideline for the corresponding repo. + +For basic support, click Issues in the command bar or post a question to [Stack Overflow](http://stackoverflow.com/questions/tagged/azure-rtos+threadx) using the `threadx` and `azure-rtos` tags. + +Professional support plans (https://azure.microsoft.com/en-us/support/options/) are available from Microsoft. + +# Additional Resources + +The following are references to additional Azure RTOS and Azure IoT in general: +| | | +|---|---| +| TraceX Installer | https://aka.ms/azrtos-tracex-installer | +| Azure RTOS Documentation and Guides: | https://docs.microsoft.com/azure/rtos | +| Azure RTOS Website: | https://azure.microsoft.com/services/rtos/ | +| Azure RTOS Sales Questions: | https://azure-rtos.ms-iot-contact.com/ | +| For technical questions check out Microsoft Q/A for Azure IoT: | https://aka.ms/QnA/azure-rtos | +| Internet of Things Show for latest announcements and online training: | https://aka.ms/iotshow | +| IoT Tech Community: | https://aka.ms/community/azure-rtos | \ No newline at end of file diff --git a/3rd_party/threadx/SECURITY.md b/3rd_party/threadx/SECURITY.md new file mode 100644 index 00000000..323bf81c --- /dev/null +++ b/3rd_party/threadx/SECURITY.md @@ -0,0 +1,35 @@ +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). \ No newline at end of file diff --git a/3rd_party/threadx/common/CMakeLists.txt b/3rd_party/threadx/common/CMakeLists.txt new file mode 100644 index 00000000..335c5e6c --- /dev/null +++ b/3rd_party/threadx/common/CMakeLists.txt @@ -0,0 +1,208 @@ +function(target_sources_if_not_overridden filename) + list(FIND TX_SRC_OVERRIDES ${filename} OVERRIDE_FOUND) + if( OVERRIDE_FOUND EQUAL -1 ) + # message(STATUS "** Using original ${filename} from common/src **") + target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/${filename}) + endif() +endfunction() + +# These files can be overridden by setting them in the variable list named TX_SRC_OVERRIDES +target_sources_if_not_overridden("tx_thread_delete.c") +target_sources_if_not_overridden("tx_thread_reset.c") + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_cleanup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_block_release.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_cleanup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_search.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_release.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_cleanup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_set_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_high_level.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_kernel_enter.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_kernel_setup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_misra.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_cleanup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_priority_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_cleanup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_front_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_receive.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_send_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_ceiling_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_cleanup.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_put_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_entry_exit_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_identify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_preemption_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_priority_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_relinquish.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_shell_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_sleep.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_analyze.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_error_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_error_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_preempt_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_terminate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_time_slice.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_time_slice_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_timeout.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_wait_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_time_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_time_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_expiration_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_performance_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_performance_system_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_system_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_system_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_buffer_full_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_event_filter.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_event_unfilter.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_interrupt_control.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_isr_enter_insert.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_isr_exit_insert.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_object_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_object_unregister.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_user_event_insert.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_block_release.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_release.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_set_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_front_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_receive.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_send_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_ceiling_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_prioritize.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_put_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_entry_exit_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_preemption_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_priority_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_relinquish.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_terminate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_time_slice_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_wait_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_info_get.c + + # {{END_TARGET_SOURCES}} +) + +# Add the Common/inc directory to the project include list +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) + diff --git a/3rd_party/threadx/tx_api.h b/3rd_party/threadx/common/inc/tx_api.h similarity index 94% rename from 3rd_party/threadx/tx_api.h rename to 3rd_party/threadx/common/inc/tx_api.h index 52a1307e..8b7f45e0 100644 --- a/3rd_party/threadx/tx_api.h +++ b/3rd_party/threadx/common/inc/tx_api.h @@ -1,23 +1,11 @@ /**************************************************************************/ /* */ -/* Copyright (c) 1996-2017 by Express Logic Inc. */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ /* */ -/* This software is copyrighted by and is the sole property of Express */ -/* Logic, Inc. All rights, title, ownership, or other interests */ -/* in the software remain the property of Express Logic, Inc. This */ -/* software may only be used in accordance with the corresponding */ -/* license agreement. Any unauthorized use, duplication, transmission, */ -/* distribution, or disclosure of this software is expressly forbidden. */ -/* */ -/* This Copyright notice may not be removed or modified without prior */ -/* written consent of Express Logic, Inc. */ -/* */ -/* Express Logic, Inc. reserves the right to modify this software */ -/* without notice. */ -/* */ -/* Express Logic, Inc. info@expresslogic.com */ -/* 11423 West Bernardo Court www.expresslogic.com */ -/* San Diego, CA 92127 */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ /* */ /**************************************************************************/ @@ -38,10 +26,10 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* tx_api.h PORTABLE C */ -/* 5.8 */ +/* 6.1.6 */ /* AUTHOR */ /* */ -/* William E. Lamie, Express Logic, Inc. */ +/* William E. Lamie, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ @@ -55,71 +43,32 @@ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 12-12-2005 William E. Lamie Initial Version 5.0 */ -/* 04-02-2007 William E. Lamie Modified comment(s), and */ -/* replaced UL constant */ -/* modifier with ULONG cast, */ -/* resulting in version 5.1 */ -/* 12-12-2008 William E. Lamie Modified comment(s), and */ -/* added trace constants, */ -/* resulting in version 5.2 */ -/* 07-04-2009 William E. Lamie Modified comment(s), and */ -/* changed the start of user */ -/* trace events to 4096, */ -/* resulting in version 5.3 */ -/* 12-12-2009 William E. Lamie Modified comment(s), changed */ -/* the definition of TX_NULL */ -/* to a pointer type, added */ -/* TX_MEMSET macro, modified */ -/* priority-inheritance struct */ -/* members in TX_THREAD,changed*/ -/* user event comments, added */ -/* callback for tracking thread*/ -/* scheduling, merged event */ -/* logging and MULTI run-time */ -/* error checking support, */ -/* changed type of all internal*/ -/* structure members used for */ -/* counting to UINT, and added */ -/* safety critical exception */ -/* logic, resulting in */ -/* version 5.4 */ -/* 07-15-2011 William E. Lamie Modified comment(s), added */ -/* defines for major/minor */ -/* version information, and */ -/* removed unused original */ -/* threshold mutex structure */ -/* member, resulting in */ -/* version 5.5 */ -/* 11-01-2012 William E. Lamie Modified comment(s), and */ -/* modified minor version */ -/* define, resulting in */ -/* version 5.6 */ -/* 05-01-2015 William E. Lamie Modified comment(s), modified */ -/* code for MISRA compliance, */ -/* modified minor version */ -/* define, added thread start */ -/* macro for performing port */ -/* and/or user specified */ -/* processing when a thread */ -/* starts, and added constant */ -/* TX_TIMER_TICKS_PER_SECOND */ -/* for use by other middleware */ -/* components as a common time */ -/* reference, resulting in */ -/* version 5.7 */ -/* 06-01-2017 William E. Lamie Modified comment(s), changed */ -/* minor version constant, */ -/* added suspension sequence to*/ -/* verify cleanup is still */ -/* necessary, made MISRA */ -/* compatibility changes, */ -/* added alignment type for */ -/* memory pools, corrected */ -/* compiler warnings in macro */ -/* definitions, added support */ -/* for optional extensions, */ -/* resulting in version 5.8 */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 William E. Lamie Modified comment(s), and */ +/* updated product constants, */ +/* added new thread execution */ +/* state TX_PRIORITY_CHANGE, */ +/* added macros for casting */ +/* pointers to ALIGN_TYPE, */ +/* resulting in version 6.1 */ +/* 10-16-2020 William E. Lamie Modified comment(s), and */ +/* increased patch version, */ +/* resulting in version 6.1.1 */ +/* 11-09-2020 Yuxin Zhou Modified comment(s), and */ +/* moved TX_THREAD_GET_SYSTEM_ */ +/* STATE to tx_api.h, */ +/* resulting in version 6.1.2 */ +/* 12-31-2020 William E. Lamie Modified comment(s), and */ +/* increased patch version, */ +/* resulting in version 6.1.3 */ +/* 03-02-2021 Scott Larson Modified comment(s), and */ +/* order defines numerically, */ +/* add option to remove FileX */ +/* pointer, */ +/* resulting in version 6.1.5 */ +/* 04-02-2021 Scott Larson Modified comment(s), and */ +/* update patch number, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -149,9 +98,13 @@ extern "C" { /* Define the major/minor version information that can be used by the application and the ThreadX source as well. */ +#define AZURE_RTOS_THREADX +#define THREADX_MAJOR_VERSION 6 +#define THREADX_MINOR_VERSION 1 +#define THREADX_PATCH_VERSION 6 + +/* Define the following symbol for backward compatibility */ #define EL_PRODUCT_THREADX -#define THREADX_MAJOR_VERSION 5 -#define THREADX_MINOR_VERSION 8 /* API input parameters and general constants. */ @@ -202,13 +155,13 @@ extern "C" { #define TX_FILE ((UINT) 11) #define TX_TCP_IP ((UINT) 12) #define TX_MUTEX_SUSP ((UINT) 13) +#define TX_PRIORITY_CHANGE ((UINT) 14) /* API return values. */ #define TX_SUCCESS ((UINT) 0x00) #define TX_DELETED ((UINT) 0x01) -#define TX_NO_MEMORY ((UINT) 0x10) #define TX_POOL_ERROR ((UINT) 0x02) #define TX_PTR_ERROR ((UINT) 0x03) #define TX_WAIT_ERROR ((UINT) 0x04) @@ -223,6 +176,7 @@ extern "C" { #define TX_NO_INSTANCE ((UINT) 0x0D) #define TX_THREAD_ERROR ((UINT) 0x0E) #define TX_PRIORITY_ERROR ((UINT) 0x0F) +#define TX_NO_MEMORY ((UINT) 0x10) #define TX_START_ERROR ((UINT) 0x10) #define TX_DELETE_ERROR ((UINT) 0x11) #define TX_RESUME_ERROR ((UINT) 0x12) @@ -254,7 +208,7 @@ extern "C" { #endif -/* Event numbers 0 through 4095 are reserved by Express Logic. Specific event assignments are: +/* Event numbers 0 through 4095 are reserved by Azure RTOS. Specific event assignments are: ThreadX events: 1-199 FileX events: 200-299 @@ -476,7 +430,9 @@ typedef struct TX_THREAD_STRUCT TX_THREAD_EXTENSION_2 /* Define a pointer type for FileX extensions. */ +#ifndef TX_NO_FILEX_POINTER VOID *tx_thread_filex_ptr; +#endif /* Define the priority inheritance variables. These will be used to manage priority inheritance changes applied to this thread @@ -1146,7 +1102,6 @@ UINT _tx_trace_interrupt_control(UINT new_posture); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING - /* Services with MULTI runtime error checking ThreadX. */ #define tx_block_allocate _txr_block_allocate @@ -1844,7 +1799,6 @@ VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL *inte VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, VOID **highest_stack); 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); UINT _tx_misra_always_true(void); - UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **pointer); UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); @@ -1868,7 +1822,14 @@ VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIM 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_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)); #define TX_MEMSET(a,b,c) _tx_misra_memset((a), (UINT) (b), (UINT) (c)) #define TX_UCHAR_POINTER_ADD(a,b) _tx_misra_uchar_pointer_add((UCHAR *) (a), (ULONG) (b)) @@ -1888,8 +1849,6 @@ UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) #define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) _tx_misra_trace_event_insert((ULONG) (i), (VOID *) (a), (ULONG) (b), (ULONG) (c), (ULONG) (d), (ULONG) (e), ((ULONG) TX_TRACE_TIME_SOURCE)); #endif #define TX_LOOP_FOREVER (_tx_misra_always_true() == TX_TRUE) - - #define TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_indirect_void_to_uchar_pointer_convert((a)) #define TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(a) _tx_misra_uchar_to_indirect_uchar_pointer_convert((a)) #define TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_block_pool_to_uchar_pointer_convert((a)) @@ -1916,6 +1875,14 @@ UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) #define TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT(a) _tx_misra_const_char_to_char_pointer_convert((a)) #define TX_VOID_TO_THREAD_POINTER_CONVERT(a) _tx_misra_void_to_thread_pointer_convert((a)) #define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_char_to_uchar_pointer_convert((a)) +#define TX_EVENT_FLAGS_GROUP_NOT_USED(a) _tx_misra_event_flags_group_not_used((a)) +#define TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(a) _tx_misra_event_flags_set_notify_not_used((a)) +#define TX_QUEUE_NOT_USED(a) _tx_misra_queue_not_used((a)) +#define TX_QUEUE_SEND_NOTIFY_NOT_USED(a) _tx_misra_queue_send_notify_not_used((a)) +#define TX_SEMAPHORE_NOT_USED(a) _tx_misra_semaphore_not_used((a)) +#define TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(a) _tx_misra_semaphore_put_notify_not_used((a)) +#define TX_THREAD_NOT_USED(a) _tx_misra_thread_not_used((a)) +#define TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(a) _tx_misra_thread_entry_exit_notify_not_used((a)) #else @@ -1933,6 +1900,8 @@ UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) #define TX_ULONG_POINTER_DIF(a,b) ((ULONG)(((ULONG *) (a)) - ((ULONG *) (b)))) #define TX_POINTER_TO_ULONG_CONVERT(a) ((ULONG) ((VOID *) (a))) #define TX_ULONG_TO_POINTER_CONVERT(a) ((VOID *) ((ULONG) (a))) +#define TX_POINTER_TO_ALIGN_TYPE_CONVERT(a) ((ALIGN_TYPE) ((VOID *) (a))) +#define TX_ALIGN_TYPE_TO_POINTER_CONVERT(a) ((VOID *) ((ALIGN_TYPE) (a))) #define TX_TIMER_POINTER_DIF(a,b) ((ULONG)(((TX_TIMER_INTERNAL **) (a)) - ((TX_TIMER_INTERNAL **) (b)))) #define TX_TIMER_POINTER_ADD(a,b) (((TX_TIMER_INTERNAL **) (a)) + ((ULONG) (b))) #define TX_USER_TIMER_POINTER_GET(a,b) { \ @@ -1943,8 +1912,6 @@ UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) (b) = (TX_TIMER *) working_ptr; \ } #define TX_LOOP_FOREVER ((UINT) 1) - - #define TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR **) ((VOID *) (a))) #define TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(a) ((UCHAR **) ((VOID *) (a))) #define TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a))) @@ -1974,6 +1941,30 @@ UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) #define TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT(a) ((CHAR *) ((VOID *) (a))) #define TX_VOID_TO_THREAD_POINTER_CONVERT(a) ((TX_THREAD *) ((VOID *) (a))) #define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a))) +#ifndef TX_EVENT_FLAGS_GROUP_NOT_USED +#define TX_EVENT_FLAGS_GROUP_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED +#define TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_QUEUE_NOT_USED +#define TX_QUEUE_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_QUEUE_SEND_NOTIFY_NOT_USED +#define TX_QUEUE_SEND_NOTIFY_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_SEMAPHORE_NOT_USED +#define TX_SEMAPHORE_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_SEMAPHORE_PUT_NOTIFY_NOT_USED +#define TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_THREAD_NOT_USED +#define TX_THREAD_NOT_USED(a) ((void)(a)) +#endif +#ifndef TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED +#define TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(a) ((void)(a)) +#endif #endif @@ -2231,6 +2222,13 @@ void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hex #endif +/* Define the get system state macro. By default, it simply maps to the variable _tx_thread_system_state. */ +/* Note that prior to Azure RTOS 6.1, this symbol was defined in tx_thread.h. */ +#ifndef TX_THREAD_GET_SYSTEM_STATE +#define TX_THREAD_GET_SYSTEM_STATE() _tx_thread_system_state +#endif + + /* Determine if a C++ compiler is being used. If so, complete the standard diff --git a/3rd_party/threadx/common/inc/tx_block_pool.h b/3rd_party/threadx/common/inc/tx_block_pool.h new file mode 100644 index 00000000..2c3be454 --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_block_pool.h @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_block_pool.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX block memory management component, */ +/* including all data types and external references. It is assumed */ +/* that tx_api.h and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_BLOCK_POOL_H +#define TX_BLOCK_POOL_H + + +/* Define block memory control specific data definitions. */ + +#define TX_BLOCK_POOL_ID ((ULONG) 0x424C4F43) + + +/* Determine if in-line component initialization is supported by the + caller. */ + +#ifdef TX_INVOKE_INLINE_INITIALIZATION + +/* Yes, in-line initialization is supported, remap the block memory pool + initialization function. */ + +#ifndef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +#define _tx_block_pool_initialize() \ + _tx_block_pool_created_ptr = TX_NULL; \ + _tx_block_pool_created_count = TX_EMPTY +#else +#define _tx_block_pool_initialize() \ + _tx_block_pool_created_ptr = TX_NULL; \ + _tx_block_pool_created_count = TX_EMPTY; \ + _tx_block_pool_performance_allocate_count = ((ULONG) 0); \ + _tx_block_pool_performance_release_count = ((ULONG) 0); \ + _tx_block_pool_performance_suspension_count = ((ULONG) 0); \ + _tx_block_pool_performance_timeout_count = ((ULONG) 0) +#endif +#define TX_BLOCK_POOL_INIT +#else + +/* No in-line initialization is supported, use standard function call. */ +VOID _tx_block_pool_initialize(VOID); +#endif + + +/* Define internal block memory pool management function prototypes. */ + +VOID _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence); + + +/* Block pool management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_BLOCK_POOL_INIT +#define BLOCK_POOL_DECLARE +#else +#define BLOCK_POOL_DECLARE extern +#endif + + +/* Define the head pointer of the created block pool list. */ + +BLOCK_POOL_DECLARE TX_BLOCK_POOL * _tx_block_pool_created_ptr; + + +/* Define the variable that holds the number of created block pools. */ + +BLOCK_POOL_DECLARE ULONG _tx_block_pool_created_count; + + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + +/* Define the total number of block allocates. */ + +BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_allocate_count; + + +/* Define the total number of block releases. */ + +BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_release_count; + + +/* Define the total number of block pool suspensions. */ + +BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_suspension_count; + + +/* Define the total number of block pool timeouts. */ + +BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_timeout_count; + + +#endif + + +/* Define default post block pool delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_BLOCK_POOL_DELETE_PORT_COMPLETION +#define TX_BLOCK_POOL_DELETE_PORT_COMPLETION(p) +#endif + + +#endif diff --git a/3rd_party/threadx/common/inc/tx_byte_pool.h b/3rd_party/threadx/common/inc/tx_byte_pool.h new file mode 100644 index 00000000..6bcc9c9c --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_byte_pool.h @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_byte_pool.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX byte memory management component, */ +/* including all data types and external references. It is assumed */ +/* that tx_api.h and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_BYTE_POOL_H +#define TX_BYTE_POOL_H + + +/* Define byte memory control specific data definitions. */ + +#define TX_BYTE_POOL_ID ((ULONG) 0x42595445) + +#ifndef TX_BYTE_BLOCK_FREE +#define TX_BYTE_BLOCK_FREE ((ULONG) 0xFFFFEEEEUL) +#endif + +#ifndef TX_BYTE_BLOCK_MIN +#define TX_BYTE_BLOCK_MIN ((ULONG) 20) +#endif + +#ifndef TX_BYTE_POOL_MIN +#define TX_BYTE_POOL_MIN ((ULONG) 100) +#endif + + +/* Determine if in-line component initialization is supported by the + caller. */ + +#ifdef TX_INVOKE_INLINE_INITIALIZATION + +/* Yes, in-line initialization is supported, remap the byte memory pool + initialization function. */ + +#ifndef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +#define _tx_byte_pool_initialize() \ + _tx_byte_pool_created_ptr = TX_NULL; \ + _tx_byte_pool_created_count = TX_EMPTY +#else +#define _tx_byte_pool_initialize() \ + _tx_byte_pool_created_ptr = TX_NULL; \ + _tx_byte_pool_created_count = TX_EMPTY; \ + _tx_byte_pool_performance_allocate_count = ((ULONG) 0); \ + _tx_byte_pool_performance_release_count = ((ULONG) 0); \ + _tx_byte_pool_performance_merge_count = ((ULONG) 0); \ + _tx_byte_pool_performance_split_count = ((ULONG) 0); \ + _tx_byte_pool_performance_search_count = ((ULONG) 0); \ + _tx_byte_pool_performance_suspension_count = ((ULONG) 0); \ + _tx_byte_pool_performance_timeout_count = ((ULONG) 0) +#endif +#define TX_BYTE_POOL_INIT +#else + +/* No in-line initialization is supported, use standard function call. */ +VOID _tx_byte_pool_initialize(VOID); +#endif + + +/* Define internal byte memory pool management function prototypes. */ + +UCHAR *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size); +VOID _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence); + + +/* Byte pool management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_BYTE_POOL_INIT +#define BYTE_POOL_DECLARE +#else +#define BYTE_POOL_DECLARE extern +#endif + + +/* Define the head pointer of the created byte pool list. */ + +BYTE_POOL_DECLARE TX_BYTE_POOL * _tx_byte_pool_created_ptr; + + +/* Define the variable that holds the number of created byte pools. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_created_count; + + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + +/* Define the total number of allocates. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_allocate_count; + + +/* Define the total number of releases. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_release_count; + + +/* Define the total number of adjacent memory fragment merges. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_merge_count; + + +/* Define the total number of memory fragment splits. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_split_count; + + +/* Define the total number of memory fragments searched during allocation. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_search_count; + + +/* Define the total number of byte pool suspensions. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_suspension_count; + + +/* Define the total number of byte pool timeouts. */ + +BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_timeout_count; + + +#endif + + +/* Define default post byte pool delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_BYTE_POOL_DELETE_PORT_COMPLETION +#define TX_BYTE_POOL_DELETE_PORT_COMPLETION(p) +#endif + + +#endif diff --git a/3rd_party/threadx/common/inc/tx_event_flags.h b/3rd_party/threadx/common/inc/tx_event_flags.h new file mode 100644 index 00000000..4406003b --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_event_flags.h @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_event_flags.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX event flags management component, */ +/* including all data types and external references. It is assumed */ +/* that tx_api.h and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_EVENT_FLAGS_H +#define TX_EVENT_FLAGS_H + + +/* Define event flags control specific data definitions. */ + +#define TX_EVENT_FLAGS_ID ((ULONG) 0x4456444E) +#define TX_EVENT_FLAGS_AND_MASK ((UINT) 0x2) +#define TX_EVENT_FLAGS_CLEAR_MASK ((UINT) 0x1) + + +/* Determine if in-line component initialization is supported by the + caller. */ +#ifdef TX_INVOKE_INLINE_INITIALIZATION + +/* Yes, in-line initialization is supported, remap the event flag initialization + function. */ + +#ifndef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO +#define _tx_event_flags_initialize() \ + _tx_event_flags_created_ptr = TX_NULL; \ + _tx_event_flags_created_count = TX_EMPTY +#else +#define _tx_event_flags_initialize() \ + _tx_event_flags_created_ptr = TX_NULL; \ + _tx_event_flags_created_count = TX_EMPTY; \ + _tx_event_flags_performance_set_count = ((ULONG) 0); \ + _tx_event_flags_performance_get_count = ((ULONG) 0); \ + _tx_event_flags_performance_suspension_count = ((ULONG) 0); \ + _tx_event_flags_performance_timeout_count = ((ULONG) 0) +#endif +#define TX_EVENT_FLAGS_INIT +#else + +/* No in-line initialization is supported, use standard function call. */ +VOID _tx_event_flags_initialize(VOID); +#endif + + +/* Define internal event flags management function prototypes. */ + +VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence); + + +/* Event flags management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_EVENT_FLAGS_INIT +#define EVENT_FLAGS_DECLARE +#else +#define EVENT_FLAGS_DECLARE extern +#endif + + +/* Define the head pointer of the created event flags list. */ + +EVENT_FLAGS_DECLARE TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr; + + +/* Define the variable that holds the number of created event flag groups. */ + +EVENT_FLAGS_DECLARE ULONG _tx_event_flags_created_count; + + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + +/* Define the total number of event flag sets. */ + +EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_set_count; + + +/* Define the total number of event flag gets. */ + +EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_get_count; + + +/* Define the total number of event flag suspensions. */ + +EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_suspension_count; + + +/* Define the total number of event flag timeouts. */ + +EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_timeout_count; + + +#endif + +/* Define default post event flag group delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION +#define TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(g) +#endif + + +#endif + diff --git a/3rd_party/threadx/common/inc/tx_initialize.h b/3rd_party/threadx/common/inc/tx_initialize.h new file mode 100644 index 00000000..625ecdb9 --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_initialize.h @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_initialize.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX initialization component, including */ +/* data types and external references. It is assumed that tx_api.h */ +/* and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_INITIALIZE_H +#define TX_INITIALIZE_H + + +/* Define constants that indicate initialization is in progress. */ + +#define TX_INITIALIZE_IN_PROGRESS ((ULONG) 0xF0F0F0F0UL) +#define TX_INITIALIZE_ALMOST_DONE ((ULONG) 0xF0F0F0F1UL) +#define TX_INITIALIZE_IS_FINISHED ((ULONG) 0x00000000UL) + + +/* Define internal initialization function prototypes. */ + +VOID _tx_initialize_high_level(VOID); +VOID _tx_initialize_kernel_setup(VOID); +VOID _tx_initialize_low_level(VOID); + + +/* Define the macro for adding additional port-specific global data. This macro is defined + as white space, unless defined by tx_port.h. */ + +#ifndef TX_PORT_SPECIFIC_DATA +#define TX_PORT_SPECIFIC_DATA +#endif + + +/* Define the macro for adding additional port-specific pre and post initialization processing. + These macros is defined as white space, unless defined by tx_port.h. */ + +#ifndef TX_PORT_SPECIFIC_PRE_INITIALIZATION +#define TX_PORT_SPECIFIC_PRE_INITIALIZATION +#endif + +#ifndef TX_PORT_SPECIFIC_POST_INITIALIZATION +#define TX_PORT_SPECIFIC_POST_INITIALIZATION +#endif + +#ifndef TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION +#endif + + +/* Initialization component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_INITIALIZE_INIT +#define INITIALIZE_DECLARE +#else +#define INITIALIZE_DECLARE extern +#endif + + +/* Define the unused memory pointer. The value of the first available + memory address is placed in this variable in the low-level + initialization function. The content of this variable is passed + to the application's system definition function. */ + +INITIALIZE_DECLARE VOID *_tx_initialize_unused_memory; + + +#endif diff --git a/3rd_party/threadx/common/inc/tx_mutex.h b/3rd_party/threadx/common/inc/tx_mutex.h new file mode 100644 index 00000000..d06ec972 --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_mutex.h @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_mutex.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX mutex management component, */ +/* including all data types and external references. It is assumed */ +/* that tx_api.h and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_MUTEX_H +#define TX_MUTEX_H + + +/* Define mutex control specific data definitions. */ + +#define TX_MUTEX_ID ((ULONG) 0x4D555445) + + +/* Determine if in-line component initialization is supported by the + caller. */ + +#ifdef TX_INVOKE_INLINE_INITIALIZATION + +/* Yes, in-line initialization is supported, remap the mutex initialization + function. */ + +#ifndef TX_MUTEX_ENABLE_PERFORMANCE_INFO +#define _tx_mutex_initialize() \ + _tx_mutex_created_ptr = TX_NULL; \ + _tx_mutex_created_count = TX_EMPTY +#else +#define _tx_mutex_initialize() \ + _tx_mutex_created_ptr = TX_NULL; \ + _tx_mutex_created_count = TX_EMPTY; \ + _tx_mutex_performance_put_count = ((ULONG) 0); \ + _tx_mutex_performance_get_count = ((ULONG) 0); \ + _tx_mutex_performance_suspension_count = ((ULONG) 0); \ + _tx_mutex_performance_timeout_count = ((ULONG) 0); \ + _tx_mutex_performance_priority_inversion_count = ((ULONG) 0); \ + _tx_mutex_performance__priority_inheritance_count = ((ULONG) 0) +#endif +#define TX_MUTEX_INIT +#else + +/* No in-line initialization is supported, use standard function call. */ +VOID _tx_mutex_initialize(VOID); +#endif + + +/* Define internal mutex management function prototypes. */ + +VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence); +VOID _tx_mutex_thread_release(TX_THREAD *thread_ptr); +VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority); + + +/* Mutex management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_MUTEX_INIT +#define MUTEX_DECLARE +#else +#define MUTEX_DECLARE extern +#endif + + +/* Define the head pointer of the created mutex list. */ + +MUTEX_DECLARE TX_MUTEX * _tx_mutex_created_ptr; + + +/* Define the variable that holds the number of created mutexes. */ + +MUTEX_DECLARE ULONG _tx_mutex_created_count; + + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + +/* Define the total number of mutex puts. */ + +MUTEX_DECLARE ULONG _tx_mutex_performance_put_count; + + +/* Define the total number of mutex gets. */ + +MUTEX_DECLARE ULONG _tx_mutex_performance_get_count; + + +/* Define the total number of mutex suspensions. */ + +MUTEX_DECLARE ULONG _tx_mutex_performance_suspension_count; + + +/* Define the total number of mutex timeouts. */ + +MUTEX_DECLARE ULONG _tx_mutex_performance_timeout_count; + + +/* Define the total number of priority inversions. */ + +MUTEX_DECLARE ULONG _tx_mutex_performance_priority_inversion_count; + + +/* Define the total number of priority inheritance conditions. */ + +MUTEX_DECLARE ULONG _tx_mutex_performance__priority_inheritance_count; + + +#endif + + +/* Define default post mutex delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_MUTEX_DELETE_PORT_COMPLETION +#define TX_MUTEX_DELETE_PORT_COMPLETION(m) +#endif + + +#endif diff --git a/3rd_party/threadx/common/inc/tx_queue.h b/3rd_party/threadx/common/inc/tx_queue.h new file mode 100644 index 00000000..52c37bef --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_queue.h @@ -0,0 +1,175 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_queue.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX queue management component, */ +/* including all data types and external references. It is assumed */ +/* that tx_api.h and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_QUEUE_H +#define TX_QUEUE_H + + +/* Define queue control specific data definitions. */ + +#define TX_QUEUE_ID ((ULONG) 0x51554555) + + +/* Determine if in-line component initialization is supported by the + caller. */ +#ifdef TX_INVOKE_INLINE_INITIALIZATION + +/* Yes, in-line initialization is supported, remap the queue initialization + function. */ + +#ifndef TX_QUEUE_ENABLE_PERFORMANCE_INFO +#define _tx_queue_initialize() \ + _tx_queue_created_ptr = TX_NULL; \ + _tx_queue_created_count = TX_EMPTY +#else +#define _tx_queue_initialize() \ + _tx_queue_created_ptr = TX_NULL; \ + _tx_queue_created_count = TX_EMPTY; \ + _tx_queue_performance_messages_sent_count = ((ULONG) 0); \ + _tx_queue_performance__messages_received_count = ((ULONG) 0); \ + _tx_queue_performance_empty_suspension_count = ((ULONG) 0); \ + _tx_queue_performance_full_suspension_count = ((ULONG) 0); \ + _tx_queue_performance_timeout_count = ((ULONG) 0) +#endif +#define TX_QUEUE_INIT +#else + +/* No in-line initialization is supported, use standard function call. */ +VOID _tx_queue_initialize(VOID); +#endif + + +/* Define the message copy macro. Note that the source and destination + pointers must be modified since they are used subsequently. */ + +#ifndef TX_QUEUE_MESSAGE_COPY +#define TX_QUEUE_MESSAGE_COPY(s, d, z) \ + *(d)++ = *(s)++; \ + if ((z) > ((UINT) 1)) \ + { \ + while (--(z)) \ + { \ + *(d)++ = *(s)++; \ + } \ + } +#endif + + +/* Define internal queue management function prototypes. */ + +VOID _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence); + + +/* Queue management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_QUEUE_INIT +#define QUEUE_DECLARE +#else +#define QUEUE_DECLARE extern +#endif + + +/* Define the head pointer of the created queue list. */ + +QUEUE_DECLARE TX_QUEUE * _tx_queue_created_ptr; + + +/* Define the variable that holds the number of created queues. */ + +QUEUE_DECLARE ULONG _tx_queue_created_count; + + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + +/* Define the total number of messages sent. */ + +QUEUE_DECLARE ULONG _tx_queue_performance_messages_sent_count; + + +/* Define the total number of messages received. */ + +QUEUE_DECLARE ULONG _tx_queue_performance__messages_received_count; + + +/* Define the total number of queue empty suspensions. */ + +QUEUE_DECLARE ULONG _tx_queue_performance_empty_suspension_count; + + +/* Define the total number of queue full suspensions. */ + +QUEUE_DECLARE ULONG _tx_queue_performance_full_suspension_count; + + +/* Define the total number of queue full errors. */ + +QUEUE_DECLARE ULONG _tx_queue_performance_full_error_count; + + +/* Define the total number of queue timeouts. */ + +QUEUE_DECLARE ULONG _tx_queue_performance_timeout_count; + + +#endif + + +/* Define default post queue delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_QUEUE_DELETE_PORT_COMPLETION +#define TX_QUEUE_DELETE_PORT_COMPLETION(q) +#endif + + +#endif + diff --git a/3rd_party/threadx/common/inc/tx_semaphore.h b/3rd_party/threadx/common/inc/tx_semaphore.h new file mode 100644 index 00000000..6f6f2756 --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_semaphore.h @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_semaphore.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX semaphore management component, */ +/* including all data types and external references. It is assumed */ +/* that tx_api.h and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_SEMAPHORE_H +#define TX_SEMAPHORE_H + + +/* Define semaphore control specific data definitions. */ + +#define TX_SEMAPHORE_ID ((ULONG) 0x53454D41) + + +/* Determine if in-line component initialization is supported by the + caller. */ +#ifdef TX_INVOKE_INLINE_INITIALIZATION + /* Yes, in-line initialization is supported, remap the + semaphore initialization function. */ +#ifndef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO +#define _tx_semaphore_initialize() \ + _tx_semaphore_created_ptr = TX_NULL; \ + _tx_semaphore_created_count = TX_EMPTY +#else +#define _tx_semaphore_initialize() \ + _tx_semaphore_created_ptr = TX_NULL; \ + _tx_semaphore_created_count = TX_EMPTY; \ + _tx_semaphore_performance_put_count = ((ULONG) 0); \ + _tx_semaphore_performance_get_count = ((ULONG) 0); \ + _tx_semaphore_performance_suspension_count = ((ULONG) 0); \ + _tx_semaphore_performance_timeout_count = ((ULONG) 0) +#endif +#define TX_SEMAPHORE_INIT +#else + /* No in-line initialization is supported, use standard + function call. */ +VOID _tx_semaphore_initialize(VOID); +#endif + + +/* Define internal semaphore management function prototypes. */ + +VOID _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence); + + +/* Semaphore management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_SEMAPHORE_INIT +#define SEMAPHORE_DECLARE +#else +#define SEMAPHORE_DECLARE extern +#endif + + +/* Define the head pointer of the created semaphore list. */ + +SEMAPHORE_DECLARE TX_SEMAPHORE * _tx_semaphore_created_ptr; + + +/* Define the variable that holds the number of created semaphores. */ + +SEMAPHORE_DECLARE ULONG _tx_semaphore_created_count; + + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + +/* Define the total number of semaphore puts. */ + +SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_put_count; + + +/* Define the total number of semaphore gets. */ + +SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_get_count; + + +/* Define the total number of semaphore suspensions. */ + +SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_suspension_count; + + +/* Define the total number of semaphore timeouts. */ + +SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_timeout_count; + + +#endif + + +/* Define default post semaphore delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_SEMAPHORE_DELETE_PORT_COMPLETION +#define TX_SEMAPHORE_DELETE_PORT_COMPLETION(s) +#endif + + +#endif + diff --git a/3rd_party/threadx/common/inc/tx_thread.h b/3rd_party/threadx/common/inc/tx_thread.h new file mode 100644 index 00000000..94657016 --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_thread.h @@ -0,0 +1,530 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_thread.h PORTABLE C */ +/* 6.1.2 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX thread control component, including */ +/* data types and external references. It is assumed that tx_api.h */ +/* and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* 11-09-2020 Yuxin Zhou Modified comment(s), and */ +/* moved TX_THREAD_GET_SYSTEM_ */ +/* STATE to tx_api.h, */ +/* resulting in version 6.1.2 */ +/* */ +/**************************************************************************/ + +#ifndef TX_THREAD_H +#define TX_THREAD_H + + +/* Define thread control specific data definitions. */ + +#define TX_THREAD_ID ((ULONG) 0x54485244) +#define TX_THREAD_PRIORITY_GROUP_MASK ((ULONG) 0xFF) +#define TX_THREAD_EXECUTE_LOG_SIZE ((UINT) 8) + + +/* Define the MOD32 bit set macro that is used to set/clear a priority bit within a specific + priority group. */ + +#if TX_MAX_PRIORITIES > 32 +#define MAP_INDEX (map_index) +#ifndef TX_MOD32_BIT_SET +#define TX_MOD32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)%((UINT)32))); +#endif +#else +#define MAP_INDEX (0) +#ifndef TX_MOD32_BIT_SET +#define TX_MOD32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a))); +#endif +#endif + + +/* Define the DIV32 bit set macro that is used to set/clear a priority group bit and is + only necessary when using priorities greater than 32. */ + +#if TX_MAX_PRIORITIES > 32 +#ifndef TX_DIV32_BIT_SET +#define TX_DIV32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)/((UINT) 32))); +#endif +#endif + + +/* Define state change macro that can be used by run-mode debug agents to keep track of thread + state changes. By default, it is mapped to white space. */ + +#ifndef TX_THREAD_STATE_CHANGE +#define TX_THREAD_STATE_CHANGE(a, b) +#endif + + +/* Define the macro to get the current thread pointer. This is particularly useful in SMP + versions of ThreadX to add additional processing. The default implementation is to simply + access the global current thread pointer directly. */ + +#ifndef TX_THREAD_GET_CURRENT +#define TX_THREAD_GET_CURRENT(a) (a) = _tx_thread_current_ptr; +#endif + + +/* Define the macro to set the current thread pointer. This is particularly useful in SMP + versions of ThreadX to add additional processing. The default implementation is to simply + access the global current thread pointer directly. */ + +#ifndef TX_THREAD_SET_CURRENT +#define TX_THREAD_SET_CURRENT(a) _tx_thread_current_ptr = (a); +#endif + + +/* Define the get system state macro. By default, it simply maps to the variable _tx_thread_system_state. */ +/* This symbol is moved to tx_api.h. Therefore removed from this file. +#ifndef TX_THREAD_GET_SYSTEM_STATE +#define TX_THREAD_GET_SYSTEM_STATE() _tx_thread_system_state +#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. */ + +#ifndef TX_THREAD_SYSTEM_RETURN_CHECK +#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = (ULONG) _tx_thread_preempt_disable; (c) = (c) | TX_THREAD_GET_SYSTEM_STATE(); +#endif + + +/* Define the timeout setup macro used in _tx_thread_create. */ + +#ifndef TX_THREAD_CREATE_TIMEOUT_SETUP +#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \ + (t) -> tx_thread_timer.tx_timer_internal_timeout_param = TX_POINTER_TO_ULONG_CONVERT((t)); +#endif + + +/* Define the thread timeout pointer setup macro used in _tx_thread_timeout. */ + +#ifndef TX_THREAD_TIMEOUT_POINTER_SETUP +#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = TX_ULONG_TO_THREAD_POINTER_CONVERT(timeout_input); +#endif + + +/* Define the lowest bit set macro. Note, that this may be overridden + by a port specific definition if there is supporting assembly language + instructions in the architecture. */ + +#ifndef TX_LOWEST_SET_BIT_CALCULATE +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) \ + (b) = ((ULONG) 0); \ + (m) = (m) & ((~(m)) + ((ULONG) 1)); \ + if ((m) < ((ULONG) 0x10)) \ + { \ + if ((m) >= ((ULONG) 4)) \ + { \ + (m) = (m) >> ((ULONG) 2); \ + (b) = (b) + ((ULONG) 2); \ + } \ + (b) = (b) + ((m) >> ((ULONG) 1)); \ + } \ + else if ((m) < ((ULONG) 0x100)) \ + { \ + (m) = (m) >> ((ULONG) 4); \ + (b) = (b) + ((ULONG) 4); \ + if ((m) >= ((ULONG) 4)) \ + { \ + (m) = (m) >> ((ULONG) 2); \ + (b) = (b) + ((ULONG) 2); \ + } \ + (b) = (b) + ((m) >> ((ULONG) 1)); \ + } \ + else if ((m) < ((ULONG) 0x10000)) \ + { \ + (m) = (m) >> ((ULONG) 8); \ + (b) = (b) + ((ULONG) 8); \ + if ((m) >= ((ULONG) 0x10)) \ + { \ + (m) = (m) >> ((ULONG) 4); \ + (b) = (b) + ((ULONG) 4); \ + } \ + if ((m) >= ((ULONG) 4)) \ + { \ + (m) = (m) >> ((ULONG) 2); \ + (b) = (b) + ((ULONG) 2); \ + } \ + (b) = (b) + ((m) >> ((ULONG) 1)); \ + } \ + else \ + { \ + (m) = (m) >> ((ULONG) 16); \ + (b) = (b) + ((ULONG) 16); \ + if ((m) >= ((ULONG) 0x100)) \ + { \ + (m) = (m) >> ((ULONG) 8); \ + (b) = (b) + ((ULONG) 8); \ + } \ + if ((m) >= ((ULONG) 16)) \ + { \ + (m) = (m) >> ((ULONG) 4); \ + (b) = (b) + ((ULONG) 4); \ + } \ + if ((m) >= ((ULONG) 4)) \ + { \ + (m) = (m) >> ((ULONG) 2); \ + (b) = (b) + ((ULONG) 2); \ + } \ + (b) = (b) + ((m) >> ((ULONG) 1)); \ + } +#endif + + +/* Define the default thread stack checking. This can be overridden by + a particular port, which is necessary if the stack growth is from + low address to high address (the default logic is for stacks that + grow from high address to low address. */ + +#ifndef TX_THREAD_STACK_CHECK +#define TX_THREAD_STACK_CHECK(thread_ptr) \ + { \ + TX_INTERRUPT_SAVE_AREA \ + TX_DISABLE \ + if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID)) \ + { \ + if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr)) \ + { \ + (thread_ptr) -> tx_thread_stack_highest_ptr = (thread_ptr) -> tx_thread_stack_ptr; \ + } \ + if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) || \ + (*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) || \ + (((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start))) \ + { \ + TX_RESTORE \ + _tx_thread_stack_error_handler((thread_ptr)); \ + TX_DISABLE \ + } \ + if (*(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) - 1) != TX_STACK_FILL) \ + { \ + TX_RESTORE \ + _tx_thread_stack_analyze((thread_ptr)); \ + TX_DISABLE \ + } \ + } \ + TX_RESTORE \ + } +#endif + + +/* Define default post thread delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_THREAD_DELETE_PORT_COMPLETION +#define TX_THREAD_DELETE_PORT_COMPLETION(t) +#endif + + +/* Define default post thread reset macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_THREAD_RESET_PORT_COMPLETION +#define TX_THREAD_RESET_PORT_COMPLETION(t) +#endif + + +/* Define the thread create internal extension macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_THREAD_CREATE_INTERNAL_EXTENSION +#define TX_THREAD_CREATE_INTERNAL_EXTENSION(t) +#endif + + +/* Define internal thread control function prototypes. */ + +VOID _tx_thread_initialize(VOID); +VOID _tx_thread_schedule(VOID); +VOID _tx_thread_shell_entry(VOID); +VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr); +VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)); +VOID _tx_thread_stack_error(TX_THREAD *thread_ptr); +VOID _tx_thread_stack_error_handler(TX_THREAD *thread_ptr); +VOID _tx_thread_system_preempt_check(VOID); +VOID _tx_thread_system_resume(TX_THREAD *thread_ptr); +VOID _tx_thread_system_ni_resume(TX_THREAD *thread_ptr); +VOID _tx_thread_system_return(VOID); +VOID _tx_thread_system_suspend(TX_THREAD *thread_ptr); +VOID _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option); +VOID _tx_thread_time_slice(VOID); +VOID _tx_thread_timeout(ULONG timeout_input); + + +/* Thread control component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#define THREAD_DECLARE extern + + +/* Define the pointer that contains the system stack pointer. This is + utilized when control returns from a thread to the system to reset the + current stack. This is setup in the low-level initialization function. */ + +THREAD_DECLARE VOID * _tx_thread_system_stack_ptr; + + +/* Define the current thread pointer. This variable points to the currently + executing thread. If this variable is NULL, no thread is executing. */ + +THREAD_DECLARE TX_THREAD * _tx_thread_current_ptr; + + +/* Define the variable that holds the next thread to execute. It is important + to remember that this is not necessarily equal to the current thread + pointer. */ + +THREAD_DECLARE TX_THREAD * _tx_thread_execute_ptr; + + +/* Define the head pointer of the created thread list. */ + +THREAD_DECLARE TX_THREAD * _tx_thread_created_ptr; + + +/* Define the variable that holds the number of created threads. */ + +THREAD_DECLARE ULONG _tx_thread_created_count; + + +/* Define the current state variable. When this value is 0, a thread + is executing or the system is idle. Other values indicate that + interrupt or initialization processing is active. This variable is + initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is + active. */ + +THREAD_DECLARE volatile ULONG _tx_thread_system_state; + + +/* Define the 32-bit priority bit-maps. There is one priority bit map for each + 32 priority levels supported. If only 32 priorities are supported there is + only one bit map. Each bit within a priority bit map represents that one + or more threads at the associated thread priority are ready. */ + +THREAD_DECLARE ULONG _tx_thread_priority_maps[TX_MAX_PRIORITIES/32]; + + +/* Define the priority map active bit map that specifies which of the previously + defined priority maps have something set. This is only necessary if more than + 32 priorities are supported. */ + +#if TX_MAX_PRIORITIES > 32 +THREAD_DECLARE ULONG _tx_thread_priority_map_active; +#endif + + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +/* Define the 32-bit preempt priority bit maps. There is one preempt bit map + for each 32 priority levels supported. If only 32 priorities are supported + there is only one bit map. Each set set bit corresponds to a preempted priority + level that had preemption-threshold active to protect against preemption of a + range of relatively higher priority threads. */ + +THREAD_DECLARE ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32]; + + +/* Define the preempt map active bit map that specifies which of the previously + defined preempt maps have something set. This is only necessary if more than + 32 priorities are supported. */ + +#if TX_MAX_PRIORITIES > 32 +THREAD_DECLARE ULONG _tx_thread_preempted_map_active; +#endif +#endif + +/* Define the variable that holds the highest priority group ready for + execution. It is important to note that this is not necessarily the same + as the priority of the thread pointed to by _tx_execute_thread. */ + +THREAD_DECLARE UINT _tx_thread_highest_priority; + + +/* Define the array of thread pointers. Each entry represents the threads that + are ready at that priority group. For example, index 10 in this array + represents the first thread ready at priority 10. If this entry is NULL, + no threads are ready at that priority. */ + +THREAD_DECLARE TX_THREAD * _tx_thread_priority_list[TX_MAX_PRIORITIES]; + + +/* Define the global preempt disable variable. If this is non-zero, preemption is + disabled. It is used internally by ThreadX to prevent preemption of a thread in + the middle of a service that is resuming or suspending another thread. */ + +THREAD_DECLARE volatile UINT _tx_thread_preempt_disable; + + +/* Define the global function pointer for mutex cleanup on thread completion or + termination. This pointer is setup during mutex initialization. */ + +THREAD_DECLARE VOID (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr); + + +/* Define the global build options variable. This contains a bit map representing + how the ThreadX library was built. The following are the bit field definitions: + + Bit(s) Meaning + + 31 TX_NOT_INTERRUPTABLE defined + 30 TX_INLINE_THREAD_RESUME_SUSPEND define + 29-24 Priority groups 1 -> 32 priorities + 2 -> 64 priorities + 3 -> 96 priorities + + ... + + 32 -> 1024 priorities + 23 TX_TIMER_PROCESS_IN_ISR defined + 22 TX_REACTIVATE_INLINE defined + 21 TX_DISABLE_STACK_FILLING defined + 20 TX_ENABLE_STACK_CHECKING defined + 19 TX_DISABLE_PREEMPTION_THRESHOLD defined + 18 TX_DISABLE_REDUNDANT_CLEARING defined + 17 TX_DISABLE_NOTIFY_CALLBACKS defined + 16 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined + 15 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined + 14 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined + 13 TX_MUTEX_ENABLE_PERFORMANCE_INFO defined + 12 TX_QUEUE_ENABLE_PERFORMANCE_INFO defined + 11 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined + 10 TX_THREAD_ENABLE_PERFORMANCE_INFO defined + 9 TX_TIMER_ENABLE_PERFORMANCE_INFO defined + 8 TX_ENABLE_EVENT_TRACE defined + 7 TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined + 6-0 Port Specific */ + +THREAD_DECLARE ULONG _tx_build_options; + + +#ifdef TX_ENABLE_STACK_CHECKING + +/* Define the global function pointer for stack error handling. If a stack error is + detected and the application has registered a stack error handler, it will be + called via this function pointer. */ + +THREAD_DECLARE VOID (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr); + +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + +/* Define the total number of thread resumptions. Each time a thread enters the + ready state this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_resume_count; + + +/* Define the total number of thread suspensions. Each time a thread enters a + suspended state this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_suspend_count; + + +/* Define the total number of solicited thread preemptions. Each time a thread is + preempted by directly calling a ThreadX service, this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_solicited_preemption_count; + + +/* Define the total number of interrupt thread preemptions. Each time a thread is + preempted as a result of an ISR calling a ThreadX service, this variable is + incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_interrupt_preemption_count; + + +/* Define the total number of priority inversions. Each time a thread is blocked by + a mutex owned by a lower-priority thread, this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_priority_inversion_count; + + +/* Define the total number of time-slices. Each time a time-slice operation is + actually performed (another thread is setup for running) this variable is + incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_time_slice_count; + + +/* Define the total number of thread relinquish operations. Each time a thread + relinquish operation is actually performed (another thread is setup for running) + this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_relinquish_count; + + +/* Define the total number of thread timeouts. Each time a thread has a + timeout this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_timeout_count; + + +/* Define the total number of thread wait aborts. Each time a thread's suspension + is lifted by the tx_thread_wait_abort call this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_wait_abort_count; + + +/* Define the total number of idle system thread returns. Each time a thread returns to + an idle system (no other thread is ready to run) this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_idle_return_count; + + +/* Define the total number of non-idle system thread returns. Each time a thread returns to + a non-idle system (another thread is ready to run) this variable is incremented. */ + +THREAD_DECLARE ULONG _tx_thread_performance_non_idle_return_count; + + +/* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This + is a circular list, where the index points to the oldest entry. */ + +THREAD_DECLARE ULONG _tx_thread_performance__execute_log_index; +THREAD_DECLARE TX_THREAD * _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE]; + +#endif + +#endif + diff --git a/3rd_party/threadx/common/inc/tx_timer.h b/3rd_party/threadx/common/inc/tx_timer.h new file mode 100644 index 00000000..ae3a5795 --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_timer.h @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_timer.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX timer management component, including */ +/* data types and external references. It is assumed that tx_api.h */ +/* and tx_port.h have already been included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_TIMER_H +#define TX_TIMER_H + + +/* Define timer management specific data definitions. */ + +#define TX_TIMER_ID ((ULONG) 0x4154494D) +#define TX_TIMER_ENTRIES ((ULONG) 32) + + +/* Define internal timer management function prototypes. */ + +VOID _tx_timer_expiration_process(VOID); +VOID _tx_timer_initialize(VOID); +VOID _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr); +VOID _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr); +VOID _tx_timer_thread_entry(ULONG timer_thread_input); + + +/* Timer management component data declarations follow. */ + +/* Determine if the initialization function of this component is including + this file. If so, make the data definitions really happen. Otherwise, + make them extern so other functions in the component can access them. */ + +#ifdef TX_TIMER_INIT +#define TIMER_DECLARE +#else +#define TIMER_DECLARE extern +#endif + + +/* Define the system clock value that is continually incremented by the + periodic timer interrupt processing. */ + +TIMER_DECLARE volatile ULONG _tx_timer_system_clock; + + +/* Define the current time slice value. If non-zero, a time-slice is active. + Otherwise, the time_slice is not active. */ + +TIMER_DECLARE ULONG _tx_timer_time_slice; + + +/* Define the time-slice expiration flag. This is used to indicate that a time-slice + has happened. */ + +TIMER_DECLARE UINT _tx_timer_expired_time_slice; + + +/* Define the thread and application timer entry list. This list provides a direct access + method for insertion of times less than TX_TIMER_ENTRIES. */ + +TIMER_DECLARE TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES]; + + +/* Define the boundary pointers to the list. These are setup to easily manage + wrapping the list. */ + +TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_list_start; +TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_list_end; + + +/* Define the current timer pointer in the list. This pointer is moved sequentially + through the timer list by the timer interrupt handler. */ + +TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_current_ptr; + + +/* Define the timer expiration flag. This is used to indicate that a timer + has expired. */ + +TIMER_DECLARE UINT _tx_timer_expired; + + +/* Define the created timer list head pointer. */ + +TIMER_DECLARE TX_TIMER *_tx_timer_created_ptr; + + +/* Define the created timer count. */ + +TIMER_DECLARE ULONG _tx_timer_created_count; + + +/* Define the pointer to the timer that has expired and is being processed. */ + +TIMER_DECLARE TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr; + + +#ifndef TX_TIMER_PROCESS_IN_ISR + +/* Define the timer thread's control block. */ + +TIMER_DECLARE TX_THREAD _tx_timer_thread; + + +/* Define the variable that holds the timer thread's starting stack address. */ + +TIMER_DECLARE VOID *_tx_timer_stack_start; + + +/* Define the variable that holds the timer thread's stack size. */ + +TIMER_DECLARE ULONG _tx_timer_stack_size; + + +/* Define the variable that holds the timer thread's priority. */ + +TIMER_DECLARE UINT _tx_timer_priority; + +/* Define the system timer thread's stack. The default size is defined + in tx_port.h. */ + +TIMER_DECLARE ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG)) - ((UINT) 1)))/sizeof(ULONG)]; + +#else + + +/* Define the busy flag that will prevent nested timer ISR processing. */ + +TIMER_DECLARE UINT _tx_timer_processing_active; + +#endif + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + +/* Define the total number of timer activations. */ + +TIMER_DECLARE ULONG _tx_timer_performance_activate_count; + + +/* Define the total number of timer reactivations. */ + +TIMER_DECLARE ULONG _tx_timer_performance_reactivate_count; + + +/* Define the total number of timer deactivations. */ + +TIMER_DECLARE ULONG _tx_timer_performance_deactivate_count; + + +/* Define the total number of timer expirations. */ + +TIMER_DECLARE ULONG _tx_timer_performance_expiration_count; + + +/* Define the total number of timer expiration adjustments. These are required + if the expiration time is greater than the size of the timer list. In such + cases, the timer is placed at the end of the list and then reactivated + as many times as necessary to finally achieve the resulting timeout. */ + +TIMER_DECLARE ULONG _tx_timer_performance__expiration_adjust_count; + + +#endif + + +/* Define default post timer delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */ + +#ifndef TX_TIMER_DELETE_PORT_COMPLETION +#define TX_TIMER_DELETE_PORT_COMPLETION(t) +#endif + + +#endif diff --git a/3rd_party/threadx/tx_trace.h b/3rd_party/threadx/common/inc/tx_trace.h similarity index 89% rename from 3rd_party/threadx/tx_trace.h rename to 3rd_party/threadx/common/inc/tx_trace.h index 7aa9de3c..7e9c809e 100644 --- a/3rd_party/threadx/tx_trace.h +++ b/3rd_party/threadx/common/inc/tx_trace.h @@ -1,23 +1,11 @@ /**************************************************************************/ /* */ -/* Copyright (c) 1996-2017 by Express Logic Inc. */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ /* */ -/* This software is copyrighted by and is the sole property of Express */ -/* Logic, Inc. All rights, title, ownership, or other interests */ -/* in the software remain the property of Express Logic, Inc. This */ -/* software may only be used in accordance with the corresponding */ -/* license agreement. Any unauthorized use, duplication, transmission, */ -/* distribution, or disclosure of this software is expressly forbidden. */ -/* */ -/* This Copyright notice may not be removed or modified without prior */ -/* written consent of Express Logic, Inc. */ -/* */ -/* Express Logic, Inc. reserves the right to modify this software */ -/* without notice. */ -/* */ -/* Express Logic, Inc. info@expresslogic.com */ -/* 11423 West Bernardo Court www.expresslogic.com */ -/* San Diego, CA 92127 */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ /* */ /**************************************************************************/ @@ -37,10 +25,10 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* tx_trace.h PORTABLE C */ -/* 5.8 */ +/* 6.1 */ /* AUTHOR */ /* */ -/* William E. Lamie, Express Logic, Inc. */ +/* William E. Lamie, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ @@ -52,48 +40,9 @@ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 12-12-2005 William E. Lamie Initial Version 5.0 */ -/* 04-02-2007 William E. Lamie Modified comment(s), */ -/* resulting in version 5.1 */ -/* 12-12-2008 William E. Lamie Modified comment(s), added */ -/* new event definitions, */ -/* changed types to ensure the */ -/* trace has universal format, */ -/* optimized event macro, and */ -/* added filter logic and new */ -/* function prototypes, */ -/* resulting in version 5.2 */ -/* 07-04-2009 William E. Lamie Modified comment(s), removed */ -/* FileX & NetX event IDs since*/ -/* they are defined elsewhere, */ -/* and corrected priority */ -/* assignment in event trace, */ -/* resulting in version 5.3 */ -/* 12-12-2009 William E. Lamie Modified comment(s), added */ -/* defines for default source, */ -/* and added logic to insert */ -/* the thread's preemption- */ -/* threshold along with its */ -/* priority, resulting in */ -/* version 5.4 */ -/* 07-15-2011 William E. Lamie Modified comment(s), and */ -/* added variables for object */ -/* registry optimizations, */ -/* resulting in version 5.5 */ -/* 11-01-2012 William E. Lamie Modified comment(s), and */ -/* added conditional around */ -/* Trace function prototypes, */ -/* resulting in version 5.6 */ -/* 05-01-2015 William E. Lamie Modified comment(s), and */ -/* modified code for MISRA */ -/* compliance, resulting in */ -/* version 5.7 */ -/* 06-01-2017 William E. Lamie Modified comment(s), made */ -/* MISRA compatibility changes,*/ -/* and utilized macros for */ -/* system state and current */ -/* thread pointer retrieval, */ -/* resulting in version 5.8 */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ /* */ /**************************************************************************/ @@ -295,7 +244,7 @@ typedef struct TX_TRACE_OBJECT_ENTRY_STRUCT /* Define ThreadX Trace Events, along with a brief description of the additional information fields, where I1 -> Information Field 1, I2 -> Information Field 2, etc. */ -/* Event numbers 0 through 4095 are reserved by Express Logic. Specific event assignments are: +/* Event numbers 0 through 4095 are reserved by Azure RTOS. Specific event assignments are: ThreadX events: 1-199 FileX events: 200-299 diff --git a/3rd_party/threadx/common/inc/tx_user_sample.h b/3rd_party/threadx/common/inc/tx_user_sample.h new file mode 100644 index 00000000..f9d06f0d --- /dev/null +++ b/3rd_party/threadx/common/inc/tx_user_sample.h @@ -0,0 +1,274 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** User Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_user.h PORTABLE C */ +/* 6.1.5 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains user defines for configuring ThreadX in specific */ +/* ways. This file will have an effect only if the application and */ +/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */ +/* Note that all the defines in this file may also be made on the */ +/* command line when building ThreadX library and application objects. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* 03-02-2021 Scott Larson Modified comment(s), */ +/* added option to remove */ +/* FileX pointer, */ +/* resulting in version 6.1.5 */ +/* */ +/**************************************************************************/ + +#ifndef TX_USER_H +#define TX_USER_H + + +/* Define various build options for the ThreadX port. The application should either make changes + here by commenting or un-commenting the conditional compilation defined OR supply the defines + though the compiler's equivalent of the -D option. + + For maximum speed, the following should be defined: + + TX_MAX_PRIORITIES 32 + TX_DISABLE_PREEMPTION_THRESHOLD + TX_DISABLE_REDUNDANT_CLEARING + TX_DISABLE_NOTIFY_CALLBACKS + TX_NOT_INTERRUPTABLE + TX_TIMER_PROCESS_IN_ISR + TX_REACTIVATE_INLINE + TX_DISABLE_STACK_FILLING + TX_INLINE_THREAD_RESUME_SUSPEND + + For minimum size, the following should be defined: + + TX_MAX_PRIORITIES 32 + TX_DISABLE_PREEMPTION_THRESHOLD + TX_DISABLE_REDUNDANT_CLEARING + TX_DISABLE_NOTIFY_CALLBACKS + TX_NO_FILEX_POINTER + TX_NOT_INTERRUPTABLE + TX_TIMER_PROCESS_IN_ISR + + Of course, many of these defines reduce functionality and/or change the behavior of the + system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR + results in faster and smaller code, however, it increases the amount of processing in the ISR. + In addition, some services that are available in timers are not available from ISRs and will + therefore return an error if this option is used. This may or may not be desirable for a + given application. */ + + +/* Override various options with default values already assigned in tx_port.h. Please also refer + to tx_port.h for descriptions on each of these options. */ + +/* +#define TX_MAX_PRIORITIES 32 +#define TX_MINIMUM_STACK ???? +#define TX_THREAD_USER_EXTENSION ???? +#define TX_TIMER_THREAD_STACK_SIZE ???? +#define TX_TIMER_THREAD_PRIORITY ???? +*/ + +/* Determine if there is a FileX pointer in the thread control block. + By default, the pointer is there for legacy/backwards compatibility. + The pointer must also be there for applications using FileX. + Define this to save space in the thread control block. +*/ + +/* +#define TX_NO_FILEX_POINTER +*/ + +/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls + should be processed within the a system timer thread or directly in the timer ISR. + By default, the timer thread is used. When the following is defined, the timer expiration + processing is done directly from the timer ISR, thereby eliminating the timer thread control + block, stack, and context switching to activate it. */ + +/* +#define TX_TIMER_PROCESS_IN_ISR +*/ + +/* Determine if in-line timer reactivation should be used within the timer expiration processing. + By default, this is disabled and a function call is used. When the following is defined, + reactivating is performed in-line resulting in faster timer processing but slightly larger + code size. */ + +/* +#define TX_REACTIVATE_INLINE +*/ + +/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled, + which places an 0xEF pattern in each byte of each thread's stack. This is used by + debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */ + +/* +#define TX_DISABLE_STACK_FILLING +*/ + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +/* +#define TX_ENABLE_STACK_CHECKING +*/ + +/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is + enabled. If the application does not use preemption-threshold, it may be disabled to reduce + code size and improve performance. */ + +/* +#define TX_DISABLE_PREEMPTION_THRESHOLD +*/ + +/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears + the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary + clearing of ThreadX global variables. */ + +/* +#define TX_DISABLE_REDUNDANT_CLEARING +*/ + +/* Determine if no timer processing is required. This option will help eliminate the timer + processing when not needed. The user will also have to comment out the call to + tx_timer_interrupt, which is typically made from assembly language in + tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR + must also be used and tx_timer_initialize must be removed from ThreadX library. */ + +/* +#define TX_NO_TIMER +#ifndef TX_TIMER_PROCESS_IN_ISR +#define TX_TIMER_PROCESS_IN_ISR +#endif +*/ + +/* Determine if the notify callback option should be disabled. By default, notify callbacks are + enabled. If the application does not use notify callbacks, they may be disabled to reduce + code size and improve performance. */ + +/* +#define TX_DISABLE_NOTIFY_CALLBACKS +*/ + + +/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal + code in-line. This results in a larger image, but improves the performance of the thread + resume and suspend services. */ + +/* +#define TX_INLINE_THREAD_RESUME_SUSPEND +*/ + + +/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code + size and less processing overhead, but increases the interrupt lockout time. */ + +/* +#define TX_NOT_INTERRUPTABLE +*/ + + +/* Determine if the trace event logging code should be enabled. This causes slight increases in + code size and overhead, but provides the ability to generate system trace information which + is available for viewing in TraceX. */ + +/* +#define TX_ENABLE_EVENT_TRACE +*/ + + +/* Determine if block pool performance gathering is required by the application. When the following is + defined, ThreadX gathers various block pool performance information. */ + +/* +#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if byte pool performance gathering is required by the application. When the following is + defined, ThreadX gathers various byte pool performance information. */ + +/* +#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if event flags performance gathering is required by the application. When the following is + defined, ThreadX gathers various event flags performance information. */ + +/* +#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if mutex performance gathering is required by the application. When the following is + defined, ThreadX gathers various mutex performance information. */ + +/* +#define TX_MUTEX_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if queue performance gathering is required by the application. When the following is + defined, ThreadX gathers various queue performance information. */ + +/* +#define TX_QUEUE_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if semaphore performance gathering is required by the application. When the following is + defined, ThreadX gathers various semaphore performance information. */ + +/* +#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if thread performance gathering is required by the application. When the following is + defined, ThreadX gathers various thread performance information. */ + +/* +#define TX_THREAD_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if timer performance gathering is required by the application. When the following is + defined, ThreadX gathers various timer performance information. */ + +/* +#define TX_TIMER_ENABLE_PERFORMANCE_INFO +*/ + +#endif + diff --git a/3rd_party/threadx/common/src/tx_block_allocate.c b/3rd_party/threadx/common/src/tx_block_allocate.c new file mode 100644 index 00000000..ad00c34a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_allocate.c @@ -0,0 +1,374 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_trace.h" +#endif +#include "tx_thread.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_allocate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a block from the specified memory block */ +/* pool. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* block_ptr Pointer to place allocated block */ +/* pointer */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Suspend thread */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +TX_THREAD *thread_ptr; +UCHAR *work_ptr; +UCHAR *temp_ptr; +UCHAR **next_block_ptr; +UCHAR **return_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif +#ifdef TX_ENABLE_EVENT_LOGGING +UCHAR *log_entry_ptr; +ULONG upper_tbu; +ULONG lower_tbu; +#endif + + + /* Disable interrupts to get a block from the pool. */ + TX_DISABLE + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total allocations counter. */ + _tx_block_pool_performance_allocate_count++; + + /* Increment the number of allocations on this pool. */ + pool_ptr -> tx_block_pool_performance_allocate_count++; +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_ALLOCATE, pool_ptr, 0, wait_option, pool_ptr -> tx_block_pool_available, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time the allocate + call succeeds. */ + if (entry_ptr != TX_NULL) + { + + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + log_entry_ptr = *(UCHAR **) _tx_el_current_event; + + /* Log this kernel call. */ + TX_EL_BLOCK_ALLOCATE_INSERT + + /* Store -1 in the third event slot. */ + *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) -1; + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time the allocate + call succeeds. */ + lower_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)); + upper_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)); +#endif + + /* Determine if there is an available block. */ + if (pool_ptr -> tx_block_pool_available != ((UINT) 0)) + { + + /* Yes, a block is available. Decrement the available count. */ + pool_ptr -> tx_block_pool_available--; + + /* Pickup the current block pointer. */ + work_ptr = pool_ptr -> tx_block_pool_available_list; + + /* Return the first available block to the caller. */ + temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); + return_ptr = TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); + *return_ptr = temp_ptr; + + /* Modify the available list to point at the next block in the pool. */ + next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); + pool_ptr -> tx_block_pool_available_list = *next_block_ptr; + + /* Save the pool's address in the block for when it is released! */ + temp_ptr = TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr); + *next_block_ptr = temp_ptr; + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the byte + allocate event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the time stamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, update the entry with the address. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr); +#endif + } + } +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + /* Store the address of the allocated block. */ + *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) *block_ptr; +#endif + + /* Set status to success. */ + status = TX_SUCCESS; + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Default the return pointer to NULL. */ + return_ptr = TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); + *return_ptr = TX_NULL; + + /* Determine if the request specifies suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion. */ + status = TX_NO_MEMORY; + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Prepare for suspension of this thread. */ + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total suspensions counter. */ + _tx_block_pool_performance_suspension_count++; + + /* Increment the number of suspensions on this pool. */ + pool_ptr -> tx_block_pool_performance_suspension_count++; +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup); + + /* Setup cleanup information, i.e. this pool control + block. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr; + + /* Save the return block pointer address as well. */ + thread_ptr -> tx_thread_additional_suspend_info = (VOID *) block_ptr; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Pickup the number of suspended threads. */ + suspended_count = (pool_ptr -> tx_block_pool_suspended_count); + + /* Increment the number of suspended threads. */ + (pool_ptr -> tx_block_pool_suspended_count)++; + + /* Setup suspension list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + pool_ptr -> tx_block_pool_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = pool_ptr -> tx_block_pool_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_BLOCK_MEMORY; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the byte + allocate event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the time-stamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, update the entry with the address. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr); +#endif + } + } +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + /* Check that the event time stamp is unchanged and the call is about + to return success. A different timestamp means that a later event + wrote over the block allocate event. A return value other than + TX_SUCCESS indicates that no block was available. In those cases, + do nothing here. */ + if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) && + upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) && + ((thread_ptr -> tx_thread_suspend_status) == TX_SUCCESS)) + { + + /* Store the address of the allocated block. */ + *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) *block_ptr; + } +#endif + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Immediate return, return error completion. */ + status = TX_NO_MEMORY; + + /* Restore interrupts. */ + TX_RESTORE + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_cleanup.c b/3rd_party/threadx/common/src/tx_block_pool_cleanup.c new file mode 100644 index 00000000..12b4dcbd --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_cleanup.c @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_cleanup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes block allocate timeout and thread terminate */ +/* actions that require the block pool data structures to be cleaned */ +/* up. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to suspended thread's */ +/* control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_timeout Thread timeout processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* _tx_thread_wait_abort Thread wait abort processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) +{ + +#ifndef TX_NOT_INTERRUPTABLE +TX_INTERRUPT_SAVE_AREA +#endif + +TX_BLOCK_POOL *pool_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts to remove the suspended thread from the block pool. */ + TX_DISABLE + + /* Determine if the cleanup is still required. */ + if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_block_pool_cleanup)) + { + + /* Check for valid suspension sequence. */ + if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) + { + + /* Setup pointer to block pool control block. */ + pool_ptr = TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); + + /* Check for a NULL byte pool pointer. */ + if (pool_ptr != TX_NULL) + { + + /* Check for valid pool ID. */ + if (pool_ptr -> tx_block_pool_id == TX_BLOCK_POOL_ID) + { + + /* Determine if there are any thread suspensions. */ + if (pool_ptr -> tx_block_pool_suspended_count != TX_NO_SUSPENSIONS) + { +#else + + /* Setup pointer to block pool control block. */ + pool_ptr = TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); +#endif + + /* Yes, we still have thread suspension! */ + + /* Clear the suspension cleanup flag. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Decrement the suspended count. */ + pool_ptr -> tx_block_pool_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = pool_ptr -> tx_block_pool_suspended_count; + + /* Remove the suspended thread from the list. */ + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + pool_ptr -> tx_block_pool_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same suspension list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Determine if we need to update the head pointer. */ + if (pool_ptr -> tx_block_pool_suspension_list == thread_ptr) + { + + /* Update the list head pointer. */ + pool_ptr -> tx_block_pool_suspension_list = next_thread; + } + } + + /* Now we need to determine if this cleanup is from a terminate, timeout, + or from a wait abort. */ + if (thread_ptr -> tx_thread_state == TX_BLOCK_MEMORY) + { + + /* Timeout condition and the thread still suspended on the block pool. + Setup return error status and resume the thread. */ + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total timeouts counter. */ + _tx_block_pool_performance_timeout_count++; + + /* Increment the number of timeouts on this block pool. */ + pool_ptr -> tx_block_pool_performance_timeout_count++; +#endif + + /* Setup return status. */ + thread_ptr -> tx_thread_suspend_status = TX_NO_MEMORY; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread! */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } +#ifndef TX_NOT_INTERRUPTABLE + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_create.c b/3rd_party/threadx/common/src/tx_block_pool_create.c new file mode 100644 index 00000000..2b9cdbcf --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_create.c @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a pool of fixed-size memory blocks in the */ +/* specified memory area. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* name_ptr Pointer to block pool name */ +/* block_size Number of bytes in each block */ +/* pool_start Address of beginning of pool area */ +/* pool_size Number of bytes in the block pool */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, + VOID *pool_start, ULONG pool_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT blocks; +UINT status; +ULONG total_blocks; +UCHAR *block_ptr; +UCHAR **block_link_ptr; +UCHAR *next_block_ptr; +TX_BLOCK_POOL *next_pool; +TX_BLOCK_POOL *previous_pool; + + + /* Initialize block pool control block to all zeros. */ + TX_MEMSET(pool_ptr, 0, (sizeof(TX_BLOCK_POOL))); + + /* Round the block size up to something that is evenly divisible by + an ALIGN_TYPE (typically this is a 32-bit ULONG). This helps guarantee proper alignment. */ + block_size = (((block_size + (sizeof(ALIGN_TYPE))) - ((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); + + /* Round the pool size down to something that is evenly divisible by + an ALIGN_TYPE (typically this is a 32-bit ULONG). */ + pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); + + /* Setup the basic block pool fields. */ + pool_ptr -> tx_block_pool_name = name_ptr; + pool_ptr -> tx_block_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + pool_ptr -> tx_block_pool_size = pool_size; + pool_ptr -> tx_block_pool_block_size = (UINT) block_size; + + /* Calculate the total number of blocks. */ + total_blocks = pool_size/(block_size + (sizeof(UCHAR *))); + + /* Walk through the pool area, setting up the available block list. */ + blocks = ((UINT) 0); + block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + next_block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *)))); + while(blocks < (UINT) total_blocks) + { + + /* Yes, we have another block. Increment the block count. */ + blocks++; + + /* Setup the link to the next block. */ + block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); + *block_link_ptr = next_block_ptr; + + /* Advance to the next block. */ + block_ptr = next_block_ptr; + + /* Update the next block pointer. */ + next_block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *)))); + } + + /* Save the remaining information in the pool control block. */ + pool_ptr -> tx_block_pool_available = blocks; + pool_ptr -> tx_block_pool_total = blocks; + + /* Quickly check to make sure at least one block is in the pool. */ + if (blocks != ((UINT) 0)) + { + + /* Backup to the last block in the pool. */ + block_ptr = TX_UCHAR_POINTER_SUB(block_ptr,(block_size + (sizeof(UCHAR *)))); + + /* Set the last block's forward pointer to NULL. */ + block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); + *block_link_ptr = TX_NULL; + + /* Setup the starting pool address. */ + pool_ptr -> tx_block_pool_available_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + + /* Disable interrupts to place the block pool on the created list. */ + TX_DISABLE + + /* Setup the block pool ID to make it valid. */ + pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID; + + /* Place the block pool on the list of created block pools. First, + check for an empty list. */ + if (_tx_block_pool_created_count == TX_EMPTY) + { + + /* The created block pool list is empty. Add block pool to empty list. */ + _tx_block_pool_created_ptr = pool_ptr; + pool_ptr -> tx_block_pool_created_next = pool_ptr; + pool_ptr -> tx_block_pool_created_previous = pool_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_pool = _tx_block_pool_created_ptr; + previous_pool = next_pool -> tx_block_pool_created_previous; + + /* Place the new block pool in the list. */ + next_pool -> tx_block_pool_created_previous = pool_ptr; + previous_pool -> tx_block_pool_created_next = pool_ptr; + + /* Setup this block pool's created links. */ + pool_ptr -> tx_block_pool_created_previous = previous_pool; + pool_ptr -> tx_block_pool_created_next = next_pool; + } + + /* Increment the created count. */ + _tx_block_pool_created_count++; + + /* Optional block pool create extended processing. */ + TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, pool_ptr, name_ptr, pool_size, block_size) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), blocks, block_size, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_POOL_CREATE_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return successful status. */ + status = TX_SUCCESS; + } + else + { + + /* Not enough memory for one block, return appropriate error. */ + status = TX_SIZE_ERROR; + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_delete.c b/3rd_party/threadx/common/src/tx_block_pool_delete.c new file mode 100644 index 00000000..e6d7491c --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_delete.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified block pool. All threads */ +/* suspended on the block pool are resumed with the TX_DELETED status */ +/* code. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +UINT suspended_count; +TX_BLOCK_POOL *next_pool; +TX_BLOCK_POOL *previous_pool; + + + /* Disable interrupts to remove the block pool from the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_POOL_DELETE_INSERT + + /* Optional block pool delete extended processing. */ + TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(pool_ptr) + + /* Clear the block pool ID to make it invalid. */ + pool_ptr -> tx_block_pool_id = TX_CLEAR_ID; + + /* Decrement the number of block pools. */ + _tx_block_pool_created_count--; + + /* See if the block pool is the only one on the list. */ + if (_tx_block_pool_created_count == TX_EMPTY) + { + + /* Only created block pool, just set the created list to NULL. */ + _tx_block_pool_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_pool = pool_ptr -> tx_block_pool_created_next; + previous_pool = pool_ptr -> tx_block_pool_created_previous; + next_pool -> tx_block_pool_created_previous = previous_pool; + previous_pool -> tx_block_pool_created_next = next_pool; + + /* See if we have to update the created list head pointer. */ + if (_tx_block_pool_created_ptr == pool_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_block_pool_created_ptr = next_pool; + } + } + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Pickup the suspension information. */ + thread_ptr = pool_ptr -> tx_block_pool_suspension_list; + pool_ptr -> tx_block_pool_suspension_list = TX_NULL; + suspended_count = pool_ptr -> tx_block_pool_suspended_count; + pool_ptr -> tx_block_pool_suspended_count = TX_NO_SUSPENSIONS; + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the block pool suspension list to resume any and all threads suspended + on this block pool. */ + while (suspended_count != TX_NO_SUSPENSIONS) + { + + /* Decrement the suspension count. */ + suspended_count--; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_DELETED. */ + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + + /* Move the thread pointer ahead. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move to next thread. */ + thread_ptr = next_thread; + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_BLOCK_POOL_DELETE_PORT_COMPLETION(pool_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Release previous preempt disable. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_info_get.c b/3rd_party/threadx/common/src/tx_block_pool_info_get.c new file mode 100644 index 00000000..4837f45b --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_info_get.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified block pool. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to block pool control blk */ +/* name Destination for the pool name */ +/* available_blocks Number of free blocks in pool */ +/* total_blocks Total number of blocks in pool */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on block pool */ +/* suspended_count Destination for suspended count */ +/* next_pool Destination for pointer to next */ +/* block pool on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, + ULONG *total_blocks, TX_THREAD **first_suspended, + ULONG *suspended_count, TX_BLOCK_POOL **next_pool) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_POOL_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the block pool. */ + if (name != TX_NULL) + { + + *name = pool_ptr -> tx_block_pool_name; + } + + /* Retrieve the number of available blocks in the block pool. */ + if (available_blocks != TX_NULL) + { + + *available_blocks = (ULONG) pool_ptr -> tx_block_pool_available; + } + + /* Retrieve the total number of blocks in the block pool. */ + if (total_blocks != TX_NULL) + { + + *total_blocks = (ULONG) pool_ptr -> tx_block_pool_total; + } + + /* Retrieve the first thread suspended on this block pool. */ + if (first_suspended != TX_NULL) + { + + *first_suspended = pool_ptr -> tx_block_pool_suspension_list; + } + + /* Retrieve the number of threads suspended on this block pool. */ + if (suspended_count != TX_NULL) + { + + *suspended_count = (ULONG) pool_ptr -> tx_block_pool_suspended_count; + } + + /* Retrieve the pointer to the next block pool created. */ + if (next_pool != TX_NULL) + { + + *next_pool = pool_ptr -> tx_block_pool_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_initialize.c b/3rd_party/threadx/common/src/tx_block_pool_initialize.c new file mode 100644 index 00000000..ae062a49 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_initialize.c @@ -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 */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_block_pool.h" + + +#ifndef TX_INLINE_INITIALIZATION + +/* Locate block pool component data in this file. */ + +/* Define the head pointer of the created block pool list. */ + +TX_BLOCK_POOL * _tx_block_pool_created_ptr; + + +/* Define the variable that holds the number of created block pools. */ + +ULONG _tx_block_pool_created_count; + + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + +/* Define the total number of block allocates. */ + +ULONG _tx_block_pool_performance_allocate_count; + + +/* Define the total number of block releases. */ + +ULONG _tx_block_pool_performance_release_count; + + +/* Define the total number of block pool suspensions. */ + +ULONG _tx_block_pool_performance_suspension_count; + + +/* Define the total number of block pool timeouts. */ + +ULONG _tx_block_pool_performance_timeout_count; + +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block pool_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the block pool component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* opt out of function when */ +/* TX_INLINE_INITIALIZATION is */ +/* defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_block_pool_initialize(VOID) +{ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created block pools list and the + number of block pools created. */ + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = TX_EMPTY; + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + + /* Initialize block pool performance counters. */ + _tx_block_pool_performance_allocate_count = ((ULONG) 0); + _tx_block_pool_performance_release_count = ((ULONG) 0); + _tx_block_pool_performance_suspension_count = ((ULONG) 0); + _tx_block_pool_performance_timeout_count = ((ULONG) 0); +#endif +#endif +} +#endif diff --git a/3rd_party/threadx/common/src/tx_block_pool_performance_info_get.c b/3rd_party/threadx/common/src/tx_block_pool_performance_info_get.c new file mode 100644 index 00000000..71112031 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_performance_info_get.c @@ -0,0 +1,203 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_block_pool.h" +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* block pool. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to block pool control blk */ +/* allocates Destination for the number of */ +/* allocations from this pool */ +/* releases Destination for the number of */ +/* blocks released back to pool */ +/* suspensions Destination for number of */ +/* suspensions on this pool */ +/* timeouts Destination for number of timeouts*/ +/* on this pool */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_pool_performance_info_get(TX_BLOCK_POOL *pool_ptr, ULONG *allocates, ULONG *releases, + ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Determine if this is a legal request. */ + if (pool_ptr == TX_NULL) + { + + /* Block pool pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the pool ID is invalid. */ + else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) + { + + /* Block pool pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PERFORMANCE_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the number of allocations from this block pool. */ + if (allocates != TX_NULL) + { + + *allocates = pool_ptr -> tx_block_pool_performance_allocate_count; + } + + /* Retrieve the number of blocks released to this block pool. */ + if (releases != TX_NULL) + { + + *releases = pool_ptr -> tx_block_pool_performance_release_count; + } + + /* Retrieve the number of thread suspensions on this block pool. */ + if (suspensions != TX_NULL) + { + + *suspensions = pool_ptr -> tx_block_pool_performance_suspension_count; + } + + /* Retrieve the number of thread timeouts on this block pool. */ + if (timeouts != TX_NULL) + { + + *timeouts = pool_ptr -> tx_block_pool_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return successful completion. */ + status = TX_SUCCESS; + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (pool_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (allocates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (releases != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_block_pool_performance_system_info_get.c new file mode 100644 index 00000000..4842bc93 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_performance_system_info_get.c @@ -0,0 +1,175 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_block_pool.h" +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves block pool performance information. */ +/* */ +/* INPUT */ +/* */ +/* allocates Destination for the total number */ +/* of block allocations */ +/* releases Destination for the total number */ +/* of blocks released */ +/* suspensions Destination for the total number */ +/* of suspensions */ +/* timeouts Destination for total number of */ +/* timeouts */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_pool_performance_system_info_get(ULONG *allocates, ULONG *releases, ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the total number of block allocations. */ + if (allocates != TX_NULL) + { + + *allocates = _tx_block_pool_performance_allocate_count; + } + + /* Retrieve the total number of blocks released. */ + if (releases != TX_NULL) + { + + *releases = _tx_block_pool_performance_release_count; + } + + /* Retrieve the total number of block pool thread suspensions. */ + if (suspensions != TX_NULL) + { + + *suspensions = _tx_block_pool_performance_suspension_count; + } + + /* Retrieve the total number of block pool thread timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_block_pool_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (allocates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (releases != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_block_pool_prioritize.c b/3rd_party/threadx/common/src/tx_block_pool_prioritize.c new file mode 100644 index 00000000..551b2019 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_pool_prioritize.c @@ -0,0 +1,251 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the highest priority suspended thread at the */ +/* front of the suspension list. All other threads remain in the same */ +/* FIFO suspension order. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *priority_thread_ptr; +TX_THREAD *head_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT list_changed; + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_POOL_PRIORITIZE_INSERT + + /* Pickup the suspended count. */ + suspended_count = pool_ptr -> tx_block_pool_suspended_count; + + /* Determine if there are fewer than 2 suspended threads. */ + if (suspended_count < ((UINT) 2)) + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Determine if there how many threads are suspended on this block memory pool. */ + else if (suspended_count == ((UINT) 2)) + { + + /* Pickup the head pointer and the next pointer. */ + head_ptr = pool_ptr -> tx_block_pool_suspension_list; + next_thread = head_ptr -> tx_thread_suspended_next; + + /* Determine if the next suspended thread has a higher priority. */ + if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) + { + + /* Yes, move the list head to the next thread. */ + pool_ptr -> tx_block_pool_suspension_list = next_thread; + } + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = pool_ptr -> tx_block_pool_suspension_list; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Set the list changed flag to false. */ + list_changed = TX_FALSE; + + /* Search through the list to find the highest priority thread. */ + do + { + + /* Is the current thread higher priority? */ + if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) + { + + /* Yes, remember that this thread is the highest priority. */ + priority_thread_ptr = thread_ptr; + } + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Determine if any changes to the list have occurred while + interrupts were enabled. */ + + /* Is the list head the same? */ + if (head_ptr != pool_ptr -> tx_block_pool_suspension_list) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + else + { + + /* Is the suspended count the same? */ + if (suspended_count != pool_ptr -> tx_block_pool_suspended_count) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + } + + /* Determine if the list has changed. */ + if (list_changed == TX_FALSE) + { + + /* Move the thread pointer to the next thread. */ + thread_ptr = thread_ptr -> tx_thread_suspended_next; + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = pool_ptr -> tx_block_pool_suspension_list; + suspended_count = pool_ptr -> tx_block_pool_suspended_count; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Reset the list changed flag. */ + list_changed = TX_FALSE; + } + + } while (thread_ptr != head_ptr); + + /* Release preemption. */ + _tx_thread_preempt_disable--; + + /* Now determine if the highest priority thread is at the front + of the list. */ + if (priority_thread_ptr != head_ptr) + { + + /* No, we need to move the highest priority suspended thread to the + front of the list. */ + + /* First, remove the highest priority thread by updating the + adjacent suspended threads. */ + next_thread = priority_thread_ptr -> tx_thread_suspended_next; + previous_thread = priority_thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Now, link the highest priority thread at the front of the list. */ + previous_thread = head_ptr -> tx_thread_suspended_previous; + priority_thread_ptr -> tx_thread_suspended_next = head_ptr; + priority_thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = priority_thread_ptr; + head_ptr -> tx_thread_suspended_previous = priority_thread_ptr; + + /* Move the list head pointer to the highest priority suspended thread. */ + pool_ptr -> tx_block_pool_suspension_list = priority_thread_ptr; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + + /* Return successful status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_block_release.c b/3rd_party/threadx/common/src/tx_block_release.c new file mode 100644 index 00000000..6ac34664 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_block_release.c @@ -0,0 +1,206 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_release PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a previously allocated block to its */ +/* associated memory block pool. */ +/* */ +/* INPUT */ +/* */ +/* block_ptr Pointer to memory block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_block_release(VOID *block_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_BLOCK_POOL *pool_ptr; +TX_THREAD *thread_ptr; +UCHAR *work_ptr; +UCHAR **return_block_ptr; +UCHAR **next_block_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + + /* Disable interrupts to put this block back in the pool. */ + TX_DISABLE + + /* Pickup the pool pointer which is just previous to the starting + address of the block that the caller sees. */ + work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); + work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *))); + next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); + pool_ptr = TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT((*next_block_ptr)); + +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total releases counter. */ + _tx_block_pool_performance_release_count++; + + /* Increment the number of releases on this pool. */ + pool_ptr -> tx_block_pool_performance_release_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(block_ptr), pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&work_ptr), TX_TRACE_BLOCK_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BLOCK_RELEASE_INSERT + + /* Determine if there are any threads suspended on the block pool. */ + thread_ptr = pool_ptr -> tx_block_pool_suspension_list; + if (thread_ptr != TX_NULL) + { + + /* Remove the suspended thread from the list. */ + + /* Decrement the number of threads suspended. */ + (pool_ptr -> tx_block_pool_suspended_count)--; + + /* Pickup the suspended count. */ + suspended_count = (pool_ptr -> tx_block_pool_suspended_count); + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + pool_ptr -> tx_block_pool_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + pool_ptr -> tx_block_pool_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Return this block pointer to the suspended thread waiting for + a block. */ + return_block_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); + *return_block_ptr = work_ptr; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + } + else + { + + /* No thread is suspended for a memory block. */ + + /* Put the block back in the available list. */ + *next_block_ptr = pool_ptr -> tx_block_pool_available_list; + + /* Adjust the head pointer. */ + pool_ptr -> tx_block_pool_available_list = work_ptr; + + /* Increment the count of available blocks. */ + pool_ptr -> tx_block_pool_available++; + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Return successful completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_allocate.c b/3rd_party/threadx/common/src/tx_byte_allocate.c new file mode 100644 index 00000000..be7e28c4 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_allocate.c @@ -0,0 +1,411 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_trace.h" +#endif +#include "tx_thread.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_allocate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates bytes from the specified memory byte */ +/* pool. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* memory_ptr Pointer to place allocated bytes */ +/* pointer */ +/* memory_size Number of bytes to allocate */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Suspend thread service */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* _tx_byte_pool_search Search byte pool for memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +TX_THREAD *thread_ptr; +UCHAR *work_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT finished; +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif +#ifdef TX_ENABLE_EVENT_LOGGING +UCHAR *log_entry_ptr; +ULONG upper_tbu; +ULONG lower_tbu; +#endif + + + /* Round the memory size up to the next size that is evenly divisible by + an ALIGN_TYPE (this is typically a 32-bit ULONG). This guarantees proper alignment. */ + memory_size = (((memory_size + (sizeof(ALIGN_TYPE)))-((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total allocations counter. */ + _tx_byte_pool_performance_allocate_count++; + + /* Increment the number of allocations on this pool. */ + pool_ptr -> tx_byte_pool_performance_allocate_count++; +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_ALLOCATE, pool_ptr, 0, memory_size, wait_option, TX_TRACE_BYTE_POOL_EVENTS) + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time the allocate + call succeeds. */ + if (entry_ptr != TX_NULL) + { + + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + log_entry_ptr = *(UCHAR **) _tx_el_current_event; + + /* Log this kernel call. */ + TX_EL_BYTE_ALLOCATE_INSERT + + /* Store -1 in the fourth event slot. */ + *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) -1; + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time the allocate + call succeeds. */ + lower_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)); + upper_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)); +#endif + + /* Set the search finished flag to false. */ + finished = TX_FALSE; + + /* Loop to handle cases where the owner of the pool changed. */ + do + { + + /* Indicate that this thread is the current owner. */ + pool_ptr -> tx_byte_pool_owner = thread_ptr; + + /* Restore interrupts. */ + TX_RESTORE + + /* At this point, the executing thread owns the pool and can perform a search + for free memory. */ + work_ptr = _tx_byte_pool_search(pool_ptr, memory_size); + + /* Optional processing extension. */ + TX_BYTE_ALLOCATE_EXTENSION + + /* Lockout interrupts. */ + TX_DISABLE + + /* Determine if we are finished. */ + if (work_ptr != TX_NULL) + { + + /* Yes, we have found a block the search is finished. */ + finished = TX_TRUE; + } + else + { + + /* No block was found, does this thread still own the pool? */ + if (pool_ptr -> tx_byte_pool_owner == thread_ptr) + { + + /* Yes, then we have looked through the entire pool and haven't found the memory. */ + finished = TX_TRUE; + } + } + + } while (finished == TX_FALSE); + + /* Copy the pointer into the return destination. */ + *memory_ptr = (VOID *) work_ptr; + + /* Determine if memory was found. */ + if (work_ptr != TX_NULL) + { + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the byte + allocate event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, update the entry with the address. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); +#endif + } + } +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the byte + allocate event. In that case, do nothing here. */ + if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) && + upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET))) + { + /* Store the address of the allocated fragment. */ + *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) *memory_ptr; + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Set the status to success. */ + status = TX_SUCCESS; + } + else + { + + /* No memory of sufficient size was found... */ + + /* Determine if the request specifies suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_NO_MEMORY; + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Prepare for suspension of this thread. */ + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total suspensions counter. */ + _tx_byte_pool_performance_suspension_count++; + + /* Increment the number of suspensions on this pool. */ + pool_ptr -> tx_byte_pool_performance_suspension_count++; +#endif + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup); + + /* Setup cleanup information, i.e. this pool control + block. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr; + + /* Save the return memory pointer address as well. */ + thread_ptr -> tx_thread_additional_suspend_info = (VOID *) memory_ptr; + + /* Save the byte size requested. */ + thread_ptr -> tx_thread_suspend_info = memory_size; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Pickup the number of suspended threads. */ + suspended_count = pool_ptr -> tx_byte_pool_suspended_count; + + /* Increment the suspension count. */ + (pool_ptr -> tx_byte_pool_suspended_count)++; + + /* Setup suspension list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + pool_ptr -> tx_byte_pool_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = pool_ptr -> tx_byte_pool_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_BYTE_MEMORY; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the byte + allocate event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, update the entry with the address. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr); +#endif + } + } +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the byte + allocate event. In that case, do nothing here. */ + if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) && + upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET))) + { + + /* Store the address of the allocated fragment. */ + *((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) *memory_ptr; + } +#endif + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Immediate return, return error completion. */ + status = TX_NO_MEMORY; + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_cleanup.c b/3rd_party/threadx/common/src/tx_byte_pool_cleanup.c new file mode 100644 index 00000000..e8cd1a0e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_cleanup.c @@ -0,0 +1,214 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_cleanup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes byte allocate timeout and thread terminate */ +/* actions that require the byte pool data structures to be cleaned */ +/* up. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to suspended thread's */ +/* control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_timeout Thread timeout processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* _tx_thread_wait_abort Thread wait abort processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) +{ + +#ifndef TX_NOT_INTERRUPTABLE +TX_INTERRUPT_SAVE_AREA +#endif + +TX_BYTE_POOL *pool_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts to remove the suspended thread from the byte pool. */ + TX_DISABLE + + /* Determine if the cleanup is still required. */ + if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_byte_pool_cleanup)) + { + + /* Check for valid suspension sequence. */ + if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) + { + + /* Setup pointer to byte pool control block. */ + pool_ptr = TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); + + /* Check for a NULL byte pool pointer. */ + if (pool_ptr != TX_NULL) + { + + /* Check for valid pool ID. */ + if (pool_ptr -> tx_byte_pool_id == TX_BYTE_POOL_ID) + { + + /* Determine if there are any thread suspensions. */ + if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS) + { +#else + + /* Setup pointer to byte pool control block. */ + pool_ptr = TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); +#endif + + /* Thread suspended for memory... Clear the suspension cleanup flag. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Decrement the suspension count. */ + pool_ptr -> tx_byte_pool_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = pool_ptr -> tx_byte_pool_suspended_count; + + /* Remove the suspended thread from the list. */ + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + pool_ptr -> tx_byte_pool_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same suspension list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Determine if we need to update the head pointer. */ + if (pool_ptr -> tx_byte_pool_suspension_list == thread_ptr) + { + + /* Update the list head pointer. */ + pool_ptr -> tx_byte_pool_suspension_list = next_thread; + } + } + + /* Now we need to determine if this cleanup is from a terminate, timeout, + or from a wait abort. */ + if (thread_ptr -> tx_thread_state == TX_BYTE_MEMORY) + { + + /* Timeout condition and the thread still suspended on the byte pool. + Setup return error status and resume the thread. */ + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total timeouts counter. */ + _tx_byte_pool_performance_timeout_count++; + + /* Increment the number of timeouts on this byte pool. */ + pool_ptr -> tx_byte_pool_performance_timeout_count++; +#endif + + /* Setup return status. */ + thread_ptr -> tx_thread_suspend_status = TX_NO_MEMORY; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread! */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } +#ifndef TX_NOT_INTERRUPTABLE + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_create.c b/3rd_party/threadx/common/src/tx_byte_pool_create.c new file mode 100644 index 00000000..ffd35e54 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_create.c @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a pool of memory bytes in the specified */ +/* memory area. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* name_ptr Pointer to byte pool name */ +/* pool_start Address of beginning of pool area */ +/* pool_size Number of bytes in the byte pool */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UCHAR *block_ptr; +UCHAR **block_indirect_ptr; +UCHAR *temp_ptr; +TX_BYTE_POOL *next_pool; +TX_BYTE_POOL *previous_pool; +ALIGN_TYPE *free_ptr; + + + /* Initialize the byte pool control block to all zeros. */ + TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL))); + + /* Round the pool size down to something that is evenly divisible by + an ULONG. */ + pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE)); + + /* Setup the basic byte pool fields. */ + pool_ptr -> tx_byte_pool_name = name_ptr; + + /* Save the start and size of the pool. */ + pool_ptr -> tx_byte_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + pool_ptr -> tx_byte_pool_size = pool_size; + + /* Setup memory list to the beginning as well as the search pointer. */ + pool_ptr -> tx_byte_pool_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + pool_ptr -> tx_byte_pool_search = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + + /* Initially, the pool will have two blocks. One large block at the + beginning that is available and a small allocated block at the end + of the pool that is there just for the algorithm. Be sure to count + the available block's header in the available bytes count. */ + pool_ptr -> tx_byte_pool_available = pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE))); + pool_ptr -> tx_byte_pool_fragments = ((UINT) 2); + + /* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE + field that contains either the constant TX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the + owning pool (if the block is allocated). */ + + /* Calculate the end of the pool's memory area. */ + block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, pool_size); + + /* Backup the end of the pool pointer and build the pre-allocated block. */ + block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE))); + + /* Cast the pool pointer into a ULONG. */ + temp_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr); + block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); + *block_indirect_ptr = temp_ptr; + + block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *))); + block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr); + *block_indirect_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + + /* Now setup the large available block in the pool. */ + temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr); + *block_indirect_ptr = block_ptr; + block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start); + block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr); + *free_ptr = TX_BYTE_BLOCK_FREE; + + /* Clear the owner id. */ + pool_ptr -> tx_byte_pool_owner = TX_NULL; + + /* Disable interrupts to place the byte pool on the created list. */ + TX_DISABLE + + /* Setup the byte pool ID to make it valid. */ + pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID; + + /* Place the byte pool on the list of created byte pools. First, + check for an empty list. */ + if (_tx_byte_pool_created_count == TX_EMPTY) + { + + /* The created byte pool list is empty. Add byte pool to empty list. */ + _tx_byte_pool_created_ptr = pool_ptr; + pool_ptr -> tx_byte_pool_created_next = pool_ptr; + pool_ptr -> tx_byte_pool_created_previous = pool_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_pool = _tx_byte_pool_created_ptr; + previous_pool = next_pool -> tx_byte_pool_created_previous; + + /* Place the new byte pool in the list. */ + next_pool -> tx_byte_pool_created_previous = pool_ptr; + previous_pool -> tx_byte_pool_created_next = pool_ptr; + + /* Setup this byte pool's created links. */ + pool_ptr -> tx_byte_pool_created_previous = previous_pool; + pool_ptr -> tx_byte_pool_created_next = next_pool; + } + + /* Increment the number of created byte pools. */ + _tx_byte_pool_created_count++; + + /* Optional byte pool create extended processing. */ + TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BYTE_POOL, pool_ptr, name_ptr, pool_size, 0) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), pool_size, TX_POINTER_TO_ULONG_CONVERT(&block_ptr), TX_TRACE_BYTE_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BYTE_POOL_CREATE_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_delete.c b/3rd_party/threadx/common/src/tx_byte_pool_delete.c new file mode 100644 index 00000000..1d8a3fa7 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_delete.c @@ -0,0 +1,213 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified byte pool. All threads */ +/* suspended on the byte pool are resumed with the TX_DELETED status */ +/* code. */ +/* */ +/* It is important to note that the byte pool being deleted, or the */ +/* memory associated with it should not be in use when this function */ +/* is called. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +UINT suspended_count; +TX_BYTE_POOL *next_pool; +TX_BYTE_POOL *previous_pool; + + + /* Disable interrupts to remove the byte pool from the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BYTE_POOL_EVENTS) + + /* Optional byte pool delete extended processing. */ + TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(pool_ptr) + + /* Log this kernel call. */ + TX_EL_BYTE_POOL_DELETE_INSERT + + /* Clear the byte pool ID to make it invalid. */ + pool_ptr -> tx_byte_pool_id = TX_CLEAR_ID; + + /* Decrement the number of byte pools created. */ + _tx_byte_pool_created_count--; + + /* See if the byte pool is the only one on the list. */ + if (_tx_byte_pool_created_count == TX_EMPTY) + { + + /* Only created byte pool, just set the created list to NULL. */ + _tx_byte_pool_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_pool = pool_ptr -> tx_byte_pool_created_next; + previous_pool = pool_ptr -> tx_byte_pool_created_previous; + next_pool -> tx_byte_pool_created_previous = previous_pool; + previous_pool -> tx_byte_pool_created_next = next_pool; + + /* See if we have to update the created list head pointer. */ + if (_tx_byte_pool_created_ptr == pool_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_byte_pool_created_ptr = next_pool; + } + } + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Pickup the suspension information. */ + thread_ptr = pool_ptr -> tx_byte_pool_suspension_list; + pool_ptr -> tx_byte_pool_suspension_list = TX_NULL; + suspended_count = pool_ptr -> tx_byte_pool_suspended_count; + pool_ptr -> tx_byte_pool_suspended_count = TX_NO_SUSPENSIONS; + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the byte pool list to resume any and all threads suspended + on this byte pool. */ + while (suspended_count != TX_NO_SUSPENSIONS) + { + + /* Decrement the suspension count. */ + suspended_count--; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_DELETED. */ + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + + /* Move the thread pointer ahead. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move to next thread. */ + thread_ptr = next_thread; + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_BYTE_POOL_DELETE_PORT_COMPLETION(pool_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Release previous preempt disable. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_info_get.c b/3rd_party/threadx/common/src/tx_byte_pool_info_get.c new file mode 100644 index 00000000..b13e8e31 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_info_get.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified byte pool. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to byte pool control block*/ +/* name Destination for the pool name */ +/* available_bytes Number of free bytes in byte pool */ +/* fragments Number of fragments in byte pool */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on byte pool */ +/* suspended_count Destination for suspended count */ +/* next_pool Destination for pointer to next */ +/* byte pool on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, + ULONG *fragments, TX_THREAD **first_suspended, + ULONG *suspended_count, TX_BYTE_POOL **next_pool) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BYTE_POOL_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the byte pool. */ + if (name != TX_NULL) + { + + *name = pool_ptr -> tx_byte_pool_name; + } + + /* Retrieve the number of available bytes in the byte pool. */ + if (available_bytes != TX_NULL) + { + + *available_bytes = pool_ptr -> tx_byte_pool_available; + } + + /* Retrieve the total number of bytes in the byte pool. */ + if (fragments != TX_NULL) + { + + *fragments = (ULONG) pool_ptr -> tx_byte_pool_fragments; + } + + /* Retrieve the first thread suspended on this byte pool. */ + if (first_suspended != TX_NULL) + { + + *first_suspended = pool_ptr -> tx_byte_pool_suspension_list; + } + + /* Retrieve the number of threads suspended on this byte pool. */ + if (suspended_count != TX_NULL) + { + + *suspended_count = (ULONG) pool_ptr -> tx_byte_pool_suspended_count; + } + + /* Retrieve the pointer to the next byte pool created. */ + if (next_pool != TX_NULL) + { + + *next_pool = pool_ptr -> tx_byte_pool_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_initialize.c b/3rd_party/threadx/common/src/tx_byte_pool_initialize.c new file mode 100644 index 00000000..92b6b106 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_initialize.c @@ -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 */ +/** */ +/** Byte Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_byte_pool.h" + + +#ifndef TX_INLINE_INITIALIZATION + +/* Locate byte pool component data in this file. */ + +/* Define the head pointer of the created byte pool list. */ + +TX_BYTE_POOL * _tx_byte_pool_created_ptr; + + +/* Define the variable that holds the number of created byte pools. */ + +ULONG _tx_byte_pool_created_count; + + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + +/* Define the total number of allocates. */ + +ULONG _tx_byte_pool_performance_allocate_count; + + +/* Define the total number of releases. */ + +ULONG _tx_byte_pool_performance_release_count; + + +/* Define the total number of adjacent memory fragment merges. */ + +ULONG _tx_byte_pool_performance_merge_count; + + +/* Define the total number of memory fragment splits. */ + +ULONG _tx_byte_pool_performance_split_count; + + +/* Define the total number of memory fragments searched during allocation. */ + +ULONG _tx_byte_pool_performance_search_count; + + +/* Define the total number of byte pool suspensions. */ + +ULONG _tx_byte_pool_performance_suspension_count; + + +/* Define the total number of byte pool timeouts. */ + +ULONG _tx_byte_pool_performance_timeout_count; + +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the byte pool component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* opt out of function when */ +/* TX_INLINE_INITIALIZATION is */ +/* defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_byte_pool_initialize(VOID) +{ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created byte pools list and the + number of byte pools created. */ + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = TX_EMPTY; + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Initialize byte pool performance counters. */ + _tx_byte_pool_performance_allocate_count = ((ULONG) 0); + _tx_byte_pool_performance_release_count = ((ULONG) 0); + _tx_byte_pool_performance_merge_count = ((ULONG) 0); + _tx_byte_pool_performance_split_count = ((ULONG) 0); + _tx_byte_pool_performance_search_count = ((ULONG) 0); + _tx_byte_pool_performance_suspension_count = ((ULONG) 0); + _tx_byte_pool_performance_timeout_count = ((ULONG) 0); +#endif +#endif +} +#endif diff --git a/3rd_party/threadx/common/src/tx_byte_pool_performance_info_get.c b/3rd_party/threadx/common/src/tx_byte_pool_performance_info_get.c new file mode 100644 index 00000000..c3f685fd --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_performance_info_get.c @@ -0,0 +1,255 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_byte_pool.h" +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* byte pool. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to byte pool control block*/ +/* allocates Destination for number of */ +/* allocates on this pool */ +/* releases Destination for number of */ +/* releases on this pool */ +/* fragments_searched Destination for number of */ +/* fragments searched during */ +/* allocation */ +/* merges Destination for number of adjacent*/ +/* free fragments merged */ +/* splits Destination for number of */ +/* fragments split during */ +/* allocation */ +/* suspensions Destination for number of */ +/* suspensions on this pool */ +/* timeouts Destination for number of timeouts*/ +/* on this byte pool */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases, + ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + +UINT status; + + + /* Determine if this is a legal request. */ + if (pool_ptr == TX_NULL) + { + + /* Byte pool pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the pool ID is invalid. */ + else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) + { + + /* Byte pool pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PERFORMANCE_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the number of allocates on this byte pool. */ + if (allocates != TX_NULL) + { + + *allocates = pool_ptr -> tx_byte_pool_performance_allocate_count; + } + + /* Retrieve the number of releases on this byte pool. */ + if (releases != TX_NULL) + { + + *releases = pool_ptr -> tx_byte_pool_performance_release_count; + } + + /* Retrieve the number of fragments searched in this byte pool. */ + if (fragments_searched != TX_NULL) + { + + *fragments_searched = pool_ptr -> tx_byte_pool_performance_search_count; + } + + /* Retrieve the number of fragments merged on this byte pool. */ + if (merges != TX_NULL) + { + + *merges = pool_ptr -> tx_byte_pool_performance_merge_count; + } + + /* Retrieve the number of fragment splits on this byte pool. */ + if (splits != TX_NULL) + { + + *splits = pool_ptr -> tx_byte_pool_performance_split_count; + } + + /* Retrieve the number of suspensions on this byte pool. */ + if (suspensions != TX_NULL) + { + + *suspensions = pool_ptr -> tx_byte_pool_performance_suspension_count; + } + + /* Retrieve the number of timeouts on this byte pool. */ + if (timeouts != TX_NULL) + { + + *timeouts = pool_ptr -> tx_byte_pool_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + status = TX_SUCCESS; + } + + /* Return completion status. */ + return(status); +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (pool_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (allocates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (releases != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (fragments_searched != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (merges != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (splits != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_byte_pool_performance_system_info_get.c new file mode 100644 index 00000000..4d804952 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_performance_system_info_get.c @@ -0,0 +1,223 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_byte_pool.h" +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves byte pool performance information. */ +/* */ +/* INPUT */ +/* */ +/* allocates Destination for total number of */ +/* allocates */ +/* releases Destination for total number of */ +/* releases */ +/* fragments_searched Destination for total number of */ +/* fragments searched during */ +/* allocation */ +/* merges Destination for total number of */ +/* adjacent free fragments merged */ +/* splits Destination for total number of */ +/* fragments split during */ +/* allocation */ +/* suspensions Destination for total number of */ +/* suspensions */ +/* timeouts Destination for total number of */ +/* timeouts */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_pool_performance_system_info_get(ULONG *allocates, ULONG *releases, + ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the total number of byte pool allocates. */ + if (allocates != TX_NULL) + { + + *allocates = _tx_byte_pool_performance_allocate_count; + } + + /* Retrieve the total number of byte pool releases. */ + if (releases != TX_NULL) + { + + *releases = _tx_byte_pool_performance_release_count; + } + + /* Retrieve the total number of byte pool fragments searched. */ + if (fragments_searched != TX_NULL) + { + + *fragments_searched = _tx_byte_pool_performance_search_count; + } + + /* Retrieve the total number of byte pool fragments merged. */ + if (merges != TX_NULL) + { + + *merges = _tx_byte_pool_performance_merge_count; + } + + /* Retrieve the total number of byte pool fragment splits. */ + if (splits != TX_NULL) + { + + *splits = _tx_byte_pool_performance_split_count; + } + + /* Retrieve the total number of byte pool suspensions. */ + if (suspensions != TX_NULL) + { + + *suspensions = _tx_byte_pool_performance_suspension_count; + } + + /* Retrieve the total number of byte pool timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_byte_pool_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (allocates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (releases != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (fragments_searched != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (merges != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (splits != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_prioritize.c b/3rd_party/threadx/common/src/tx_byte_pool_prioritize.c new file mode 100644 index 00000000..30f273e8 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_prioritize.c @@ -0,0 +1,251 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the highest priority suspended thread at the */ +/* front of the suspension list. All other threads remain in the same */ +/* FIFO suspension order. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *priority_thread_ptr; +TX_THREAD *head_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT list_changed; + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_byte_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BYTE_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BYTE_POOL_PRIORITIZE_INSERT + + /* Pickup the suspended count. */ + suspended_count = pool_ptr -> tx_byte_pool_suspended_count; + + /* Determine if there are fewer than 2 suspended threads. */ + if (suspended_count < ((UINT) 2)) + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Determine if there how many threads are suspended on this byte memory pool. */ + else if (suspended_count == ((UINT) 2)) + { + + /* Pickup the head pointer and the next pointer. */ + head_ptr = pool_ptr -> tx_byte_pool_suspension_list; + next_thread = head_ptr -> tx_thread_suspended_next; + + /* Determine if the next suspended thread has a higher priority. */ + if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) + { + + /* Yes, move the list head to the next thread. */ + pool_ptr -> tx_byte_pool_suspension_list = next_thread; + } + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = pool_ptr -> tx_byte_pool_suspension_list; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Set the list changed flag to false. */ + list_changed = TX_FALSE; + + /* Search through the list to find the highest priority thread. */ + do + { + + /* Is the current thread higher priority? */ + if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) + { + + /* Yes, remember that this thread is the highest priority. */ + priority_thread_ptr = thread_ptr; + } + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Determine if any changes to the list have occurred while + interrupts were enabled. */ + + /* Is the list head the same? */ + if (head_ptr != pool_ptr -> tx_byte_pool_suspension_list) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + else + { + + /* Is the suspended count the same? */ + if (suspended_count != pool_ptr -> tx_byte_pool_suspended_count) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + } + + /* Determine if the list has changed. */ + if (list_changed == TX_FALSE) + { + + /* Move the thread pointer to the next thread. */ + thread_ptr = thread_ptr -> tx_thread_suspended_next; + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = pool_ptr -> tx_byte_pool_suspension_list; + suspended_count = pool_ptr -> tx_byte_pool_suspended_count; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Reset the list changed flag. */ + list_changed = TX_FALSE; + } + + } while (thread_ptr != head_ptr); + + /* Release preemption. */ + _tx_thread_preempt_disable--; + + /* Now determine if the highest priority thread is at the front + of the list. */ + if (priority_thread_ptr != head_ptr) + { + + /* No, we need to move the highest priority suspended thread to the + front of the list. */ + + /* First, remove the highest priority thread by updating the + adjacent suspended threads. */ + next_thread = priority_thread_ptr -> tx_thread_suspended_next; + previous_thread = priority_thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Now, link the highest priority thread at the front of the list. */ + previous_thread = head_ptr -> tx_thread_suspended_previous; + priority_thread_ptr -> tx_thread_suspended_next = head_ptr; + priority_thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = priority_thread_ptr; + head_ptr -> tx_thread_suspended_previous = priority_thread_ptr; + + /* Move the list head pointer to the highest priority suspended thread. */ + pool_ptr -> tx_byte_pool_suspension_list = priority_thread_ptr; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_pool_search.c b/3rd_party/threadx/common/src/tx_byte_pool_search.c new file mode 100644 index 00000000..2e9f5194 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_pool_search.c @@ -0,0 +1,352 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_search PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches a byte pool for a memory block to satisfy */ +/* the requested number of bytes. Merging of adjacent free blocks */ +/* takes place during the search and a split of the block that */ +/* satisfies the request may occur before this function returns. */ +/* */ +/* It is assumed that this function is called with interrupts enabled */ +/* and with the tx_pool_owner field set to the thread performing the */ +/* search. Also note that the search can occur during allocation and */ +/* release of a memory block. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* memory_size Number of bytes required */ +/* */ +/* OUTPUT */ +/* */ +/* UCHAR * Pointer to the allocated memory, */ +/* if successful. Otherwise, a */ +/* NULL is returned */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_byte_allocate Allocate bytes of memory */ +/* _tx_byte_release Release bytes of memory */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UCHAR *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UCHAR *current_ptr; +UCHAR *next_ptr; +UCHAR **this_block_link_ptr; +UCHAR **next_block_link_ptr; +ULONG available_bytes; +UINT examine_blocks; +UINT first_free_block_found = TX_FALSE; +TX_THREAD *thread_ptr; +ALIGN_TYPE *free_ptr; +UCHAR *work_ptr; + + + /* Disable interrupts. */ + TX_DISABLE + + /* First, determine if there are enough bytes in the pool. */ + if (memory_size >= pool_ptr -> tx_byte_pool_available) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Not enough memory, return a NULL pointer. */ + current_ptr = TX_NULL; + } + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup ownership of the byte pool. */ + pool_ptr -> tx_byte_pool_owner = thread_ptr; + + /* Walk through the memory pool in search for a large enough block. */ + current_ptr = pool_ptr -> tx_byte_pool_search; + examine_blocks = pool_ptr -> tx_byte_pool_fragments + ((UINT) 1); + available_bytes = ((ULONG) 0); + do + { + + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total fragment search counter. */ + _tx_byte_pool_performance_search_count++; + + /* Increment the number of fragments searched on this pool. */ + pool_ptr -> tx_byte_pool_performance_search_count++; +#endif + + /* Check to see if this block is free. */ + work_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr); + if ((*free_ptr) == TX_BYTE_BLOCK_FREE) + { + + /* Determine if this is the first free block. */ + if (first_free_block_found == TX_FALSE) + { + + /* This is the first free block. */ + pool_ptr->tx_byte_pool_search = current_ptr; + + /* Set the flag to indicate we have found the first free + block. */ + first_free_block_found = TX_TRUE; + } + + /* Block is free, see if it is large enough. */ + + /* Pickup the next block's pointer. */ + this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); + next_ptr = *this_block_link_ptr; + + /* Calculate the number of bytes available in this block. */ + available_bytes = TX_UCHAR_POINTER_DIF(next_ptr, current_ptr); + available_bytes = available_bytes - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))); + + /* If this is large enough, we are done because our first-fit algorithm + has been satisfied! */ + if (available_bytes >= memory_size) + { + /* Get out of the search loop! */ + break; + } + else + { + + /* Clear the available bytes variable. */ + available_bytes = ((ULONG) 0); + + /* Not enough memory, check to see if the neighbor is + free and can be merged. */ + work_ptr = TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr); + if ((*free_ptr) == TX_BYTE_BLOCK_FREE) + { + + /* Yes, neighbor block can be merged! This is quickly accomplished + by updating the current block with the next blocks pointer. */ + next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr); + *this_block_link_ptr = *next_block_link_ptr; + + /* Reduce the fragment total. We don't need to increase the bytes + available because all free headers are also included in the available + count. */ + pool_ptr -> tx_byte_pool_fragments--; + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total merge counter. */ + _tx_byte_pool_performance_merge_count++; + + /* Increment the number of blocks merged on this pool. */ + pool_ptr -> tx_byte_pool_performance_merge_count++; +#endif + + /* See if the search pointer is affected. */ + if (pool_ptr -> tx_byte_pool_search == next_ptr) + { + + /* Yes, update the search pointer. */ + pool_ptr -> tx_byte_pool_search = current_ptr; + } + } + else + { + + /* Neighbor is not free so we can skip over it! */ + next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr); + current_ptr = *next_block_link_ptr; + + /* Decrement the examined block count to account for this one. */ + if (examine_blocks != ((UINT) 0)) + { + + examine_blocks--; + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total fragment search counter. */ + _tx_byte_pool_performance_search_count++; + + /* Increment the number of fragments searched on this pool. */ + pool_ptr -> tx_byte_pool_performance_search_count++; +#endif + } + } + } + } + else + { + + /* Block is not free, move to next block. */ + this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); + current_ptr = *this_block_link_ptr; + } + + /* Another block has been searched... decrement counter. */ + if (examine_blocks != ((UINT) 0)) + { + + examine_blocks--; + } + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if anything has changed in terms of pool ownership. */ + if (pool_ptr -> tx_byte_pool_owner != thread_ptr) + { + + /* Pool changed ownership in the brief period interrupts were + enabled. Reset the search. */ + current_ptr = pool_ptr -> tx_byte_pool_search; + examine_blocks = pool_ptr -> tx_byte_pool_fragments + ((UINT) 1); + + /* Setup our ownership again. */ + pool_ptr -> tx_byte_pool_owner = thread_ptr; + } + } while(examine_blocks != ((UINT) 0)); + + /* Determine if a block was found. If so, determine if it needs to be + split. */ + if (available_bytes != ((ULONG) 0)) + { + + /* Determine if we need to split this block. */ + if ((available_bytes - memory_size) >= ((ULONG) TX_BYTE_BLOCK_MIN)) + { + + /* Split the block. */ + next_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (memory_size + ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))))); + + /* Setup the new free block. */ + next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr); + this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); + *next_block_link_ptr = *this_block_link_ptr; + work_ptr = TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr); + *free_ptr = TX_BYTE_BLOCK_FREE; + + /* Increase the total fragment counter. */ + pool_ptr -> tx_byte_pool_fragments++; + + /* Update the current pointer to point at the newly created block. */ + *this_block_link_ptr = next_ptr; + + /* Set available equal to memory size for subsequent calculation. */ + available_bytes = memory_size; + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total split counter. */ + _tx_byte_pool_performance_split_count++; + + /* Increment the number of blocks split on this pool. */ + pool_ptr -> tx_byte_pool_performance_split_count++; +#endif + } + + /* In any case, mark the current block as allocated. */ + work_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *))); + this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); + *this_block_link_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr); + + /* Reduce the number of available bytes in the pool. */ + pool_ptr -> tx_byte_pool_available = (pool_ptr -> tx_byte_pool_available - available_bytes) - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))); + + /* Determine if the search pointer needs to be updated. This is only done + if the search pointer matches the block to be returned. */ + if (current_ptr == pool_ptr -> tx_byte_pool_search) + { + + /* Yes, update the search pointer to the next block. */ + this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr); + pool_ptr -> tx_byte_pool_search = *this_block_link_ptr; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Adjust the pointer for the application. */ + current_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))))); + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Set current pointer to NULL to indicate nothing was found. */ + current_ptr = TX_NULL; + } + } + + /* Return the search pointer. */ + return(current_ptr); +} + diff --git a/3rd_party/threadx/common/src/tx_byte_release.c b/3rd_party/threadx/common/src/tx_byte_release.c new file mode 100644 index 00000000..2d1dc7bb --- /dev/null +++ b/3rd_party/threadx/common/src/tx_byte_release.c @@ -0,0 +1,378 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_release PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns previously allocated memory to its */ +/* associated memory byte pool. */ +/* */ +/* INPUT */ +/* */ +/* memory_ptr Pointer to allocated memory */ +/* */ +/* OUTPUT */ +/* */ +/* [TX_PTR_ERROR | TX_SUCCESS] Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_byte_pool_search Search the byte pool for memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_byte_release(VOID *memory_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +TX_BYTE_POOL *pool_ptr; +TX_THREAD *thread_ptr; +UCHAR *work_ptr; +UCHAR *temp_ptr; +UCHAR *next_block_ptr; +TX_THREAD *susp_thread_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +ULONG memory_size; +ALIGN_TYPE *free_ptr; +TX_BYTE_POOL **byte_pool_ptr; +UCHAR **block_link_ptr; +UCHAR **suspend_info_ptr; + + + /* Default to successful status. */ + status = TX_SUCCESS; + + /* Set the pool pointer to NULL. */ + pool_ptr = TX_NULL; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Determine if the memory pointer is valid. */ + work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(memory_ptr); + if (work_ptr != TX_NULL) + { + + /* Back off the memory pointer to pickup its header. */ + work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))); + + /* There is a pointer, pickup the pool pointer address. */ + temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr); + if ((*free_ptr) != TX_BYTE_BLOCK_FREE) + { + + /* Pickup the pool pointer. */ + temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); + byte_pool_ptr = TX_UCHAR_TO_INDIRECT_BYTE_POOL_POINTER(temp_ptr); + pool_ptr = *byte_pool_ptr; + + /* See if we have a valid pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Return pointer error. */ + status = TX_PTR_ERROR; + } + else + { + + /* See if we have a valid pool. */ + if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) + { + + /* Return pointer error. */ + status = TX_PTR_ERROR; + + /* Reset the pool pointer is NULL. */ + pool_ptr = TX_NULL; + } + } + } + else + { + + /* Return pointer error. */ + status = TX_PTR_ERROR; + } + } + else + { + + /* Return pointer error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the pointer is valid. */ + if (pool_ptr == TX_NULL) + { + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* At this point, we know that the pointer is valid. */ + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Indicate that this thread is the current owner. */ + pool_ptr -> tx_byte_pool_owner = thread_ptr; + +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + + /* Increment the total release counter. */ + _tx_byte_pool_performance_release_count++; + + /* Increment the number of releases on this pool. */ + pool_ptr -> tx_byte_pool_performance_release_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(memory_ptr), pool_ptr -> tx_byte_pool_suspended_count, pool_ptr -> tx_byte_pool_available, TX_TRACE_BYTE_POOL_EVENTS) + + /* Log this kernel call. */ + TX_EL_BYTE_RELEASE_INSERT + + /* Release the memory. */ + temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr); + *free_ptr = TX_BYTE_BLOCK_FREE; + + /* Update the number of available bytes in the pool. */ + block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); + next_block_ptr = *block_link_ptr; + pool_ptr -> tx_byte_pool_available = + pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr); + + /* Determine if the free block is prior to current search pointer. */ + if (work_ptr < (pool_ptr -> tx_byte_pool_search)) + { + + /* Yes, update the search pointer to the released block. */ + pool_ptr -> tx_byte_pool_search = work_ptr; + } + + /* Determine if there are threads suspended on this byte pool. */ + if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS) + { + + /* Now examine the suspension list to find threads waiting for + memory. Maybe it is now available! */ + while (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS) + { + + /* Pickup the first suspended thread pointer. */ + susp_thread_ptr = pool_ptr -> tx_byte_pool_suspension_list; + + /* Pickup the size of the memory the thread is requesting. */ + memory_size = susp_thread_ptr -> tx_thread_suspend_info; + + /* Restore interrupts. */ + TX_RESTORE + + /* See if the request can be satisfied. */ + work_ptr = _tx_byte_pool_search(pool_ptr, memory_size); + + /* Optional processing extension. */ + TX_BYTE_RELEASE_EXTENSION + + /* Disable interrupts. */ + TX_DISABLE + + /* Indicate that this thread is the current owner. */ + pool_ptr -> tx_byte_pool_owner = thread_ptr; + + /* If there is not enough memory, break this loop! */ + if (work_ptr == TX_NULL) + { + + /* Break out of the loop. */ + break; + } + + /* Check to make sure the thread is still suspended. */ + if (susp_thread_ptr == pool_ptr -> tx_byte_pool_suspension_list) + { + + /* Also, makes sure the memory size is the same. */ + if (susp_thread_ptr -> tx_thread_suspend_info == memory_size) + { + + /* Remove the suspended thread from the list. */ + + /* Decrement the number of threads suspended. */ + pool_ptr -> tx_byte_pool_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = pool_ptr -> tx_byte_pool_suspended_count; + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + pool_ptr -> tx_byte_pool_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = susp_thread_ptr -> tx_thread_suspended_next; + pool_ptr -> tx_byte_pool_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = susp_thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Prepare for resumption of the thread. */ + + /* Clear cleanup routine to avoid timeout. */ + susp_thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Return this block pointer to the suspended thread waiting for + a block. */ + suspend_info_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(susp_thread_ptr -> tx_thread_additional_suspend_info); + *suspend_info_ptr = work_ptr; + + /* Clear the memory pointer to indicate that it was given to the suspended thread. */ + work_ptr = TX_NULL; + + /* Put return status into the thread control block. */ + susp_thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(susp_thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(susp_thread_ptr); +#endif + + /* Lockout interrupts. */ + TX_DISABLE + } + } + + /* Determine if the memory was given to the suspended thread. */ + if (work_ptr != TX_NULL) + { + + /* No, it wasn't given to the suspended thread. */ + + /* Put the memory back on the available list since this thread is no longer + suspended. */ + work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))))); + temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *))); + free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr); + *free_ptr = TX_BYTE_BLOCK_FREE; + + /* Update the number of available bytes in the pool. */ + block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); + next_block_ptr = *block_link_ptr; + pool_ptr -> tx_byte_pool_available = + pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr); + + /* Determine if the current pointer is before the search pointer. */ + if (work_ptr < (pool_ptr -> tx_byte_pool_search)) + { + + /* Yes, update the search pointer. */ + pool_ptr -> tx_byte_pool_search = work_ptr; + } + } + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + else + { + + /* No, threads suspended, restore interrupts. */ + TX_RESTORE + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_cleanup.c b/3rd_party/threadx/common/src/tx_event_flags_cleanup.c new file mode 100644 index 00000000..3f170976 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_cleanup.c @@ -0,0 +1,239 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_cleanup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes event flags timeout and thread terminate */ +/* actions that require the event flags data structures to be cleaned */ +/* up. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to suspended thread's */ +/* control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_timeout Thread timeout processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* _tx_thread_wait_abort Thread wait abort processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) +{ + +#ifndef TX_NOT_INTERRUPTABLE +TX_INTERRUPT_SAVE_AREA +#endif + +TX_EVENT_FLAGS_GROUP *group_ptr; +UINT suspended_count; +TX_THREAD *suspension_head; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts to remove the suspended thread from the event flags group. */ + TX_DISABLE + + /* Determine if the cleanup is still required. */ + if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_event_flags_cleanup)) + { + + /* Check for valid suspension sequence. */ + if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) + { + + /* Setup pointer to event flags control block. */ + group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); + + /* Check for a NULL event flags control block pointer. */ + if (group_ptr != TX_NULL) + { + + /* Is the group pointer ID valid? */ + if (group_ptr -> tx_event_flags_group_id == TX_EVENT_FLAGS_ID) + { + + /* Determine if there are any thread suspensions. */ + if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) + { +#else + + /* Setup pointer to event flags control block. */ + group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); +#endif + + /* Yes, we still have thread suspension! */ + + /* Clear the suspension cleanup flag. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Pickup the suspended count. */ + suspended_count = group_ptr -> tx_event_flags_group_suspended_count; + + /* Pickup the suspension head. */ + suspension_head = group_ptr -> tx_event_flags_group_suspension_list; + + /* Determine if the cleanup is being done while a set operation was interrupted. If the + suspended count is non-zero and the suspension head is NULL, the list is being processed + and cannot be touched from here. The suspension list removal will instead take place + inside the event flag set code. */ + if (suspension_head != TX_NULL) + { + + /* Remove the suspended thread from the list. */ + + /* Decrement the local suspension count. */ + suspended_count--; + + /* Store the updated suspended count. */ + group_ptr -> tx_event_flags_group_suspended_count = suspended_count; + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + group_ptr -> tx_event_flags_group_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same suspension list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Determine if we need to update the head pointer. */ + if (suspension_head == thread_ptr) + { + + /* Update the list head pointer. */ + group_ptr -> tx_event_flags_group_suspension_list = next_thread; + } + } + } + else + { + + /* In this case, the search pointer in an interrupted event flag set must be reset. */ + group_ptr -> tx_event_flags_group_reset_search = TX_TRUE; + } + + /* Now we need to determine if this cleanup is from a terminate, timeout, + or from a wait abort. */ + if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG) + { + + /* Timeout condition and the thread still suspended on the event flags group. + Setup return error status and resume the thread. */ + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + + /* Increment the total timeouts counter. */ + _tx_event_flags_performance_timeout_count++; + + /* Increment the number of timeouts on this event flags group. */ + group_ptr -> tx_event_flags_group____performance_timeout_count++; +#endif + + /* Setup return status. */ + thread_ptr -> tx_thread_suspend_status = TX_NO_EVENTS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread! Check for preemption even though we are executing + from the system timer thread right now which normally executes at the + highest priority. */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } +#ifndef TX_NOT_INTERRUPTABLE + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_create.c b/3rd_party/threadx/common/src/tx_event_flags_create.c new file mode 100644 index 00000000..807894f5 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_create.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a group of 32 event flags. All the flags are */ +/* initially in a cleared state. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to event flags group */ +/* control block */ +/* name_ptr Pointer to event flags name */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_EVENT_FLAGS_GROUP *next_group; +TX_EVENT_FLAGS_GROUP *previous_group; + + + /* Initialize event flags control block to all zeros. */ + TX_MEMSET(group_ptr, 0, (sizeof(TX_EVENT_FLAGS_GROUP))); + + /* Setup the basic event flags group fields. */ + group_ptr -> tx_event_flags_group_name = name_ptr; + + /* Disable interrupts to put the event flags group on the created list. */ + TX_DISABLE + + /* Setup the event flags ID to make it valid. */ + group_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID; + + /* Place the group on the list of created event flag groups. First, + check for an empty list. */ + if (_tx_event_flags_created_count == TX_EMPTY) + { + + /* The created event flags list is empty. Add event flag group to empty list. */ + _tx_event_flags_created_ptr = group_ptr; + group_ptr -> tx_event_flags_group_created_next = group_ptr; + group_ptr -> tx_event_flags_group_created_previous = group_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_group = _tx_event_flags_created_ptr; + previous_group = next_group -> tx_event_flags_group_created_previous; + + /* Place the new event flag group in the list. */ + next_group -> tx_event_flags_group_created_previous = group_ptr; + previous_group -> tx_event_flags_group_created_next = group_ptr; + + /* Setup this group's created links. */ + group_ptr -> tx_event_flags_group_created_previous = previous_group; + group_ptr -> tx_event_flags_group_created_next = next_group; + } + + /* Increment the number of created event flag groups. */ + _tx_event_flags_created_count++; + + /* Optional event flag group create extended processing. */ + TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, group_ptr, name_ptr, 0, 0) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_CREATE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_group), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS_CREATE_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_delete.c b/3rd_party/threadx/common/src/tx_event_flags_delete.c new file mode 100644 index 00000000..f384f126 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_delete.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified event flag group. All threads */ +/* suspended on the group are resumed with the TX_DELETED status */ +/* code. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +UINT suspended_count; +TX_EVENT_FLAGS_GROUP *next_group; +TX_EVENT_FLAGS_GROUP *previous_group; + + + /* Disable interrupts to remove the group from the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_DELETE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Optional event flags group delete extended processing. */ + TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(group_ptr) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS_DELETE_INSERT + + /* Clear the event flag group ID to make it invalid. */ + group_ptr -> tx_event_flags_group_id = TX_CLEAR_ID; + + /* Decrement the number of created event flag groups. */ + _tx_event_flags_created_count--; + + /* See if this group is the only one on the list. */ + if (_tx_event_flags_created_count == TX_EMPTY) + { + + /* Only created event flag group, just set the created list to NULL. */ + _tx_event_flags_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_group = group_ptr -> tx_event_flags_group_created_next; + previous_group = group_ptr -> tx_event_flags_group_created_previous; + next_group -> tx_event_flags_group_created_previous = previous_group; + previous_group -> tx_event_flags_group_created_next = next_group; + + /* See if we have to update the created list head pointer. */ + if (_tx_event_flags_created_ptr == group_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_event_flags_created_ptr = next_group; + } + } + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Pickup the suspension information. */ + thread_ptr = group_ptr -> tx_event_flags_group_suspension_list; + group_ptr -> tx_event_flags_group_suspension_list = TX_NULL; + suspended_count = group_ptr -> tx_event_flags_group_suspended_count; + group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS; + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the event flag suspension list to resume any and all threads + suspended on this group. */ + while (suspended_count != TX_NO_SUSPENSIONS) + { + + /* Decrement the number of suspended threads. */ + suspended_count--; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_DELETED. */ + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + + /* Move the thread pointer ahead. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move to next thread. */ + thread_ptr = next_thread; + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(group_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Release previous preempt disable. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_get.c b/3rd_party/threadx/common/src/tx_event_flags_get.c new file mode 100644 index 00000000..1e79a4cd --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_get.c @@ -0,0 +1,403 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the specified event flags from the group, */ +/* according to the get option. The get option also specifies whether */ +/* or not the retrieved flags are cleared. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block */ +/* requested_event_flags Event flags requested */ +/* get_option Specifies and/or and clear options*/ +/* actual_flags_ptr Pointer to place the actual flags */ +/* the service retrieved */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Suspend thread service */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, + UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +UINT and_request; +UINT clear_request; +ULONG current_flags; +ULONG flags_satisfied; +#ifndef TX_NOT_INTERRUPTABLE +ULONG delayed_clear_flags; +#endif +UINT suspended_count; +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +#ifndef TX_NOT_INTERRUPTABLE +UINT interrupted_set_request; +#endif + + + /* Disable interrupts to examine the event flags group. */ + TX_DISABLE + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + + /* Increment the total event flags get counter. */ + _tx_event_flags_performance_get_count++; + + /* Increment the number of event flags gets on this semaphore. */ + group_ptr -> tx_event_flags_group__performance_get_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_GET, group_ptr, requested_flags, group_ptr -> tx_event_flags_group_current, get_option, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS_GET_INSERT + + /* Pickup current flags. */ + current_flags = group_ptr -> tx_event_flags_group_current; + + /* Apply the event flag option mask. */ + and_request = (get_option & TX_AND); + +#ifdef TX_NOT_INTERRUPTABLE + + /* Check for AND condition. All flags must be present to satisfy request. */ + if (and_request == TX_AND) + { + + /* AND request is present. */ + + /* Calculate the flags present. */ + flags_satisfied = (current_flags & requested_flags); + + /* Determine if they satisfy the AND request. */ + if (flags_satisfied != requested_flags) + { + + /* No, not all the requested flags are present. Clear the flags present variable. */ + flags_satisfied = ((ULONG) 0); + } + } + else + { + + /* OR request is present. Simply or the requested flags and the current flags. */ + flags_satisfied = (current_flags & requested_flags); + } + + /* Determine if the request is satisfied. */ + if (flags_satisfied != ((ULONG) 0)) + { + + /* Return the actual event flags that satisfied the request. */ + *actual_flags_ptr = current_flags; + + /* Pickup the clear bit. */ + clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK); + + /* Determine whether or not clearing needs to take place. */ + if (clear_request == TX_TRUE) + { + + /* Yes, clear the flags that satisfied this request. */ + group_ptr -> tx_event_flags_group_current = + group_ptr -> tx_event_flags_group_current & (~requested_flags); + } + + /* Return success. */ + status = TX_SUCCESS; + } + +#else + + /* Pickup delayed clear flags. */ + delayed_clear_flags = group_ptr -> tx_event_flags_group_delayed_clear; + + /* Determine if there are any delayed clear operations pending. */ + if (delayed_clear_flags != ((ULONG) 0)) + { + + /* Yes, apply them to the current flags. */ + current_flags = current_flags & (~delayed_clear_flags); + } + + /* Check for AND condition. All flags must be present to satisfy request. */ + if (and_request == TX_AND) + { + + /* AND request is present. */ + + /* Calculate the flags present. */ + flags_satisfied = (current_flags & requested_flags); + + /* Determine if they satisfy the AND request. */ + if (flags_satisfied != requested_flags) + { + + /* No, not all the requested flags are present. Clear the flags present variable. */ + flags_satisfied = ((ULONG) 0); + } + } + else + { + + /* OR request is present. Simply AND together the requested flags and the current flags + to see if any are present. */ + flags_satisfied = (current_flags & requested_flags); + } + + /* Determine if the request is satisfied. */ + if (flags_satisfied != ((ULONG) 0)) + { + + /* Yes, this request can be handled immediately. */ + + /* Return the actual event flags that satisfied the request. */ + *actual_flags_ptr = current_flags; + + /* Pickup the clear bit. */ + clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK); + + /* Determine whether or not clearing needs to take place. */ + if (clear_request == TX_TRUE) + { + + /* Set interrupted set request flag to false. */ + interrupted_set_request = TX_FALSE; + + /* Determine if the suspension list is being processed by an interrupted + set request. */ + if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) + { + + if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL) + { + + /* Set the interrupted set request flag. */ + interrupted_set_request = TX_TRUE; + } + } + + /* Was a set request interrupted? */ + if (interrupted_set_request == TX_TRUE) + { + + /* A previous set operation is was interrupted, we need to defer the + event clearing until the set operation is complete. */ + + /* Remember the events to clear. */ + group_ptr -> tx_event_flags_group_delayed_clear = + group_ptr -> tx_event_flags_group_delayed_clear | requested_flags; + } + else + { + + /* Yes, clear the flags that satisfied this request. */ + group_ptr -> tx_event_flags_group_current = + group_ptr -> tx_event_flags_group_current & ~requested_flags; + } + } + + /* Set status to success. */ + status = TX_SUCCESS; + } + +#endif + else + { + + /* Determine if the request specifies suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion. */ + status = TX_NO_EVENTS; + } + else + { + + /* Prepare for suspension of this thread. */ + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + + /* Increment the total event flags suspensions counter. */ + _tx_event_flags_performance_suspension_count++; + + /* Increment the number of event flags suspensions on this semaphore. */ + group_ptr -> tx_event_flags_group___performance_suspension_count++; +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup); + + /* Remember which event flags we are looking for. */ + thread_ptr -> tx_thread_suspend_info = requested_flags; + + /* Save the get option as well. */ + thread_ptr -> tx_thread_suspend_option = get_option; + + /* Save the destination for the current events. */ + thread_ptr -> tx_thread_additional_suspend_info = (VOID *) actual_flags_ptr; + + /* Setup cleanup information, i.e. this event flags group control + block. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) group_ptr; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Pickup the suspended count. */ + suspended_count = group_ptr -> tx_event_flags_group_suspended_count; + + /* Setup suspension list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + group_ptr -> tx_event_flags_group_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = group_ptr -> tx_event_flags_group_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Increment the number of threads suspended. */ + group_ptr -> tx_event_flags_group_suspended_count++; + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_EVENT_FLAG; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; +#endif + } + } + else + { + + /* Immediate return, return error completion. */ + status = TX_NO_EVENTS; + } + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_info_get.c b/3rd_party/threadx/common/src/tx_event_flags_info_get.c new file mode 100644 index 00000000..feec2a9c --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_info_get.c @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified event flag */ +/* group. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to event flag group */ +/* name Destination for the event flag */ +/* group name */ +/* current_flags Current event flags */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on event flags */ +/* suspended_count Destination for suspended count */ +/* next_group Destination for pointer to next */ +/* event flag group on the created */ +/* list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, + TX_THREAD **first_suspended, ULONG *suspended_count, + TX_EVENT_FLAGS_GROUP **next_group) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the event flag group. */ + if (name != TX_NULL) + { + + *name = group_ptr -> tx_event_flags_group_name; + } + + /* Retrieve the current event flags in the event flag group. */ + if (current_flags != TX_NULL) + { + + /* Pickup the current flags and apply delayed clearing. */ + *current_flags = group_ptr -> tx_event_flags_group_current & + ~group_ptr -> tx_event_flags_group_delayed_clear; + } + + /* Retrieve the first thread suspended on this event flag group. */ + if (first_suspended != TX_NULL) + { + + *first_suspended = group_ptr -> tx_event_flags_group_suspension_list; + } + + /* Retrieve the number of threads suspended on this event flag group. */ + if (suspended_count != TX_NULL) + { + + *suspended_count = (ULONG) group_ptr -> tx_event_flags_group_suspended_count; + } + + /* Retrieve the pointer to the next event flag group created. */ + if (next_group != TX_NULL) + { + + *next_group = group_ptr -> tx_event_flags_group_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_initialize.c b/3rd_party/threadx/common/src/tx_event_flags_initialize.c new file mode 100644 index 00000000..867e684f --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_initialize.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_event_flags.h" + + +#ifndef TX_INLINE_INITIALIZATION + +/* Locate event flags component data in this file. */ +/* Define the head pointer of the created event flags list. */ + +TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr; + + +/* Define the variable that holds the number of created event flag groups. */ + +ULONG _tx_event_flags_created_count; + + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + +/* Define the total number of event flag sets. */ + +ULONG _tx_event_flags_performance_set_count; + + +/* Define the total number of event flag gets. */ + +ULONG _tx_event_flags_performance_get_count; + + +/* Define the total number of event flag suspensions. */ + +ULONG _tx_event_flags_performance_suspension_count; + + +/* Define the total number of event flag timeouts. */ + +ULONG _tx_event_flags_performance_timeout_count; + + +#endif + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the event flags component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* opt out of function when */ +/* TX_INLINE_INITIALIZATION is */ +/* defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_event_flags_initialize(VOID) +{ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created event flags list and the + number of event flags created. */ + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = TX_EMPTY; + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + + /* Initialize event flags performance counters. */ + _tx_event_flags_performance_set_count = ((ULONG) 0); + _tx_event_flags_performance_get_count = ((ULONG) 0); + _tx_event_flags_performance_suspension_count = ((ULONG) 0); + _tx_event_flags_performance_timeout_count = ((ULONG) 0); +#endif +#endif +} +#endif diff --git a/3rd_party/threadx/common/src/tx_event_flags_performance_info_get.c b/3rd_party/threadx/common/src/tx_event_flags_performance_info_get.c new file mode 100644 index 00000000..a0cc23b0 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_performance_info_get.c @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_event_flags.h" +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* event flag group. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to event flag group */ +/* sets Destination for the number of */ +/* event flag sets on this group */ +/* gets Destination for the number of */ +/* event flag gets on this group */ +/* suspensions Destination for the number of */ +/* event flag suspensions on this */ +/* group */ +/* timeouts Destination for number of timeouts*/ +/* on this event flag group */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets, + ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Determine if this is a legal request. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the event group ID is invalid. */ + else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID) + { + + /* Event flags group pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_PERFORMANCE_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the number of set operations on this event flag group. */ + if (sets != TX_NULL) + { + + *sets = group_ptr -> tx_event_flags_group_performance_set_count; + } + + /* Retrieve the number of get operations on this event flag group. */ + if (gets != TX_NULL) + { + + *gets = group_ptr -> tx_event_flags_group__performance_get_count; + } + + /* Retrieve the number of thread suspensions on this event flag group. */ + if (suspensions != TX_NULL) + { + + *suspensions = group_ptr -> tx_event_flags_group___performance_suspension_count; + } + + /* Retrieve the number of thread timeouts on this event flag group. */ + if (timeouts != TX_NULL) + { + + *timeouts = group_ptr -> tx_event_flags_group____performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return successful completion. */ + status = TX_SUCCESS; + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (group_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (sets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (gets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_event_flags_performance_system_info_get.c new file mode 100644 index 00000000..8fdbb317 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_performance_system_info_get.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_event_flags.h" +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves system event flag performance information. */ +/* */ +/* INPUT */ +/* */ +/* sets Destination for total number of */ +/* event flag sets */ +/* gets Destination for total number of */ +/* event flag gets */ +/* suspensions Destination for total number of */ +/* event flag suspensions */ +/* timeouts Destination for total number of */ +/* timeouts */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_performance_system_info_get(ULONG *sets, ULONG *gets, ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the total number of event flag set operations. */ + if (sets != TX_NULL) + { + + *sets = _tx_event_flags_performance_set_count; + } + + /* Retrieve the total number of event flag get operations. */ + if (gets != TX_NULL) + { + + *gets = _tx_event_flags_performance_get_count; + } + + /* Retrieve the total number of event flag thread suspensions. */ + if (suspensions != TX_NULL) + { + + *suspensions = _tx_event_flags_performance_suspension_count; + } + + /* Retrieve the total number of event flag thread timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_event_flags_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (sets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (gets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_set.c b/3rd_party/threadx/common/src/tx_event_flags_set.c new file mode 100644 index 00000000..9228f4cd --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_set.c @@ -0,0 +1,622 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_set PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the specified flags in the event group based on */ +/* the set option specified. All threads suspended on the group whose */ +/* get request can now be satisfied are resumed. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block */ +/* flags_to_set Event flags to set */ +/* set_option Specified either AND or OR */ +/* operation on the event flags */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Always returns success */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread_ptr; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +TX_THREAD *satisfied_list; +TX_THREAD *last_satisfied; +TX_THREAD *suspended_list; +UINT suspended_count; +ULONG current_event_flags; +ULONG requested_flags; +ULONG flags_satisfied; +ULONG *suspend_info_ptr; +UINT and_request; +UINT get_option; +UINT clear_request; +UINT preempt_check; +#ifndef TX_NOT_INTERRUPTABLE +UINT interrupted_set_request; +#endif +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*events_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *notify_group_ptr); +#endif + + + /* Disable interrupts to remove the semaphore from the created list. */ + TX_DISABLE + +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + + /* Increment the total event flags set counter. */ + _tx_event_flags_performance_set_count++; + + /* Increment the number of event flags sets on this semaphore. */ + group_ptr -> tx_event_flags_group_performance_set_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option, group_ptr -> tx_event_flags_group_suspended_count, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Log this kernel call. */ + TX_EL_EVENT_FLAGS_SET_INSERT + + /* Determine how to set this group's event flags. */ + if ((set_option & TX_EVENT_FLAGS_AND_MASK) == TX_AND) + { + +#ifndef TX_NOT_INTERRUPTABLE + + /* Set interrupted set request flag to false. */ + interrupted_set_request = TX_FALSE; + + /* Determine if the suspension list is being processed by an interrupted + set request. */ + if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) + { + + if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL) + { + + /* Set the interrupted set request flag. */ + interrupted_set_request = TX_TRUE; + } + } + + /* Was a set request interrupted? */ + if (interrupted_set_request == TX_TRUE) + { + + /* A previous set operation was interrupted, we need to defer the + event clearing until the set operation is complete. */ + + /* Remember the events to clear. */ + group_ptr -> tx_event_flags_group_delayed_clear = + group_ptr -> tx_event_flags_group_delayed_clear | ~flags_to_set; + } + else + { +#endif + + /* Previous set operation was not interrupted, simply clear the + specified flags by "ANDing" the flags into the current events + of the group. */ + group_ptr -> tx_event_flags_group_current = + group_ptr -> tx_event_flags_group_current & flags_to_set; + +#ifndef TX_NOT_INTERRUPTABLE + + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this event flag group. */ + events_set_notify = group_ptr -> tx_event_flags_group_set_notify; +#endif + + /* "OR" the flags into the current events of the group. */ + group_ptr -> tx_event_flags_group_current = + group_ptr -> tx_event_flags_group_current | flags_to_set; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Determine if there are any delayed flags to clear. */ + if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0)) + { + + /* Yes, we need to neutralize the delayed clearing as well. */ + group_ptr -> tx_event_flags_group_delayed_clear = + group_ptr -> tx_event_flags_group_delayed_clear & ~flags_to_set; + } +#endif + + /* Clear the preempt check flag. */ + preempt_check = TX_FALSE; + + /* Pickup the thread suspended count. */ + suspended_count = group_ptr -> tx_event_flags_group_suspended_count; + + /* Determine if there are any threads suspended on the event flag group. */ + if (group_ptr -> tx_event_flags_group_suspension_list != TX_NULL) + { + + /* Determine if there is just a single thread waiting on the event + flag group. */ + if (suspended_count == ((UINT) 1)) + { + + /* Single thread waiting for event flags. Bypass the multiple thread + logic. */ + + /* Setup thread pointer. */ + thread_ptr = group_ptr -> tx_event_flags_group_suspension_list; + + /* Pickup the current event flags. */ + current_event_flags = group_ptr -> tx_event_flags_group_current; + + /* Pickup the suspend information. */ + requested_flags = thread_ptr -> tx_thread_suspend_info; + + /* Pickup the suspend option. */ + get_option = thread_ptr -> tx_thread_suspend_option; + + /* Isolate the AND selection. */ + and_request = (get_option & TX_AND); + + /* Check for AND condition. All flags must be present to satisfy request. */ + if (and_request == TX_AND) + { + + /* AND request is present. */ + + /* Calculate the flags present. */ + flags_satisfied = (current_event_flags & requested_flags); + + /* Determine if they satisfy the AND request. */ + if (flags_satisfied != requested_flags) + { + + /* No, not all the requested flags are present. Clear the flags present variable. */ + flags_satisfied = ((ULONG) 0); + } + } + else + { + + /* OR request is present. Simply or the requested flags and the current flags. */ + flags_satisfied = (current_event_flags & requested_flags); + } + + /* Determine if the request is satisfied. */ + if (flags_satisfied != ((ULONG) 0)) + { + + /* Yes, resume the thread and apply any event flag + clearing. */ + + /* Set the preempt check flag. */ + preempt_check = TX_TRUE; + + /* Return the actual event flags that satisfied the request. */ + suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + *suspend_info_ptr = current_event_flags; + + /* Pickup the clear bit. */ + clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK); + + /* Determine whether or not clearing needs to take place. */ + if (clear_request == TX_TRUE) + { + + /* Yes, clear the flags that satisfied this request. */ + group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & (~requested_flags); + } + + /* Clear the suspension information in the event flag group. */ + group_ptr -> tx_event_flags_group_suspension_list = TX_NULL; + group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS; + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts to remove the semaphore from the created list. */ + TX_DISABLE +#endif + } + } + else + { + + /* Otherwise, the event flag requests of multiple threads must be + examined. */ + + /* Setup thread pointer, keep a local copy of the head pointer. */ + suspended_list = group_ptr -> tx_event_flags_group_suspension_list; + thread_ptr = suspended_list; + + /* Clear the suspended list head pointer to thwart manipulation of + the list in ISR's while we are processing here. */ + group_ptr -> tx_event_flags_group_suspension_list = TX_NULL; + + /* Setup the satisfied thread pointers. */ + satisfied_list = TX_NULL; + last_satisfied = TX_NULL; + + /* Pickup the current event flags. */ + current_event_flags = group_ptr -> tx_event_flags_group_current; + + /* Disable preemption while we process the suspended list. */ + _tx_thread_preempt_disable++; + + /* Loop to examine all of the suspended threads. */ + do + { + +#ifndef TX_NOT_INTERRUPTABLE + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE +#endif + + /* Determine if we need to reset the search. */ + if (group_ptr -> tx_event_flags_group_reset_search != TX_FALSE) + { + + /* Clear the reset search flag. */ + group_ptr -> tx_event_flags_group_reset_search = TX_FALSE; + + /* Move the thread pointer to the beginning of the search list. */ + thread_ptr = suspended_list; + + /* Reset the suspended count. */ + suspended_count = group_ptr -> tx_event_flags_group_suspended_count; + + /* Update the current events with any new ones that might + have been set in a nested set events call from an ISR. */ + current_event_flags = current_event_flags | group_ptr -> tx_event_flags_group_current; + } + + /* Save next thread pointer. */ + next_thread_ptr = thread_ptr -> tx_thread_suspended_next; + + /* Pickup the suspend information. */ + requested_flags = thread_ptr -> tx_thread_suspend_info; + + /* Pickup this thread's suspension get option. */ + get_option = thread_ptr -> tx_thread_suspend_option; + + /* Isolate the AND selection. */ + and_request = (get_option & TX_AND); + + /* Check for AND condition. All flags must be present to satisfy request. */ + if (and_request == TX_AND) + { + + /* AND request is present. */ + + /* Calculate the flags present. */ + flags_satisfied = (current_event_flags & requested_flags); + + /* Determine if they satisfy the AND request. */ + if (flags_satisfied != requested_flags) + { + + /* No, not all the requested flags are present. Clear the flags present variable. */ + flags_satisfied = ((ULONG) 0); + } + } + else + { + + /* OR request is present. Simply or the requested flags and the current flags. */ + flags_satisfied = (current_event_flags & requested_flags); + } + + /* Check to see if the thread had a timeout or wait abort during the event search processing. + If so, just set the flags satisfied to ensure the processing here removes the thread from + the suspension list. */ + if (thread_ptr -> tx_thread_state != TX_EVENT_FLAG) + { + + /* Simply set the satisfied flags to 1 in order to remove the thread from the suspension list. */ + flags_satisfied = ((ULONG) 1); + } + + /* Determine if the request is satisfied. */ + if (flags_satisfied != ((ULONG) 0)) + { + + /* Yes, this request can be handled now. */ + + /* Set the preempt check flag. */ + preempt_check = TX_TRUE; + + /* Determine if the thread is still suspended on the event flag group. If not, a wait + abort must have been done from an ISR. */ + if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG) + { + + /* Return the actual event flags that satisfied the request. */ + suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + *suspend_info_ptr = current_event_flags; + + /* Pickup the clear bit. */ + clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK); + + /* Determine whether or not clearing needs to take place. */ + if (clear_request == TX_TRUE) + { + + /* Yes, clear the flags that satisfied this request. */ + group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & ~requested_flags; + } + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + } + + /* We need to remove the thread from the suspension list and place it in the + expired list. */ + + /* See if this is the only suspended thread on the list. */ + if (thread_ptr == thread_ptr -> tx_thread_suspended_next) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + suspended_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Update the list head pointer, if removing the head of the + list. */ + if (suspended_list == thread_ptr) + { + + /* Yes, head pointer needs to be updated. */ + suspended_list = thread_ptr -> tx_thread_suspended_next; + } + } + + /* Decrement the suspension count. */ + group_ptr -> tx_event_flags_group_suspended_count--; + + /* Place this thread on the expired list. */ + if (satisfied_list == TX_NULL) + { + + /* First thread on the satisfied list. */ + satisfied_list = thread_ptr; + last_satisfied = thread_ptr; + + /* Setup initial next pointer. */ + thread_ptr -> tx_thread_suspended_next = TX_NULL; + } + else + { + + /* Not the first thread on the satisfied list. */ + + /* Link it up at the end. */ + last_satisfied -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_next = TX_NULL; + last_satisfied = thread_ptr; + } + } + + /* Copy next thread pointer to working thread ptr. */ + thread_ptr = next_thread_ptr; + + /* Decrement the suspension count. */ + suspended_count--; + + } while (suspended_count != TX_NO_SUSPENSIONS); + + /* Setup the group's suspension list head again. */ + group_ptr -> tx_event_flags_group_suspension_list = suspended_list; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Determine if there is any delayed event clearing to perform. */ + if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0)) + { + + /* Perform the delayed event clearing. */ + group_ptr -> tx_event_flags_group_current = + group_ptr -> tx_event_flags_group_current & ~(group_ptr -> tx_event_flags_group_delayed_clear); + + /* Clear the delayed event flag clear value. */ + group_ptr -> tx_event_flags_group_delayed_clear = ((ULONG) 0); + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the satisfied list, setup initial thread pointer. */ + thread_ptr = satisfied_list; + while(thread_ptr != TX_NULL) + { + + /* Get next pointer first. */ + next_thread_ptr = thread_ptr -> tx_thread_suspended_next; + + /* Disable interrupts. */ + TX_DISABLE + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupt posture. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move next thread to current. */ + thread_ptr = next_thread_ptr; + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Release thread preemption disable. */ + _tx_thread_preempt_disable--; + } + } + else + { + + /* Determine if we need to set the reset search field. */ + if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS) + { + + /* We interrupted a search of an event flag group suspension + list. Make sure we reset the search. */ + group_ptr -> tx_event_flags_group_reset_search = TX_TRUE; + } + } + + /* Restore interrupts. */ + TX_RESTORE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (events_set_notify != TX_NULL) + { + + /* Call application event flags set notification. */ + (events_set_notify)(group_ptr); + } +#endif + + /* Determine if a check for preemption is necessary. */ + if (preempt_check == TX_TRUE) + { + + /* Yes, one or more threads were resumed, check for preemption. */ + _tx_thread_system_preempt_check(); + } + } + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_event_flags_set_notify.c b/3rd_party/threadx/common/src/tx_event_flags_set_notify.c new file mode 100644 index 00000000..1dc1cb49 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_event_flags_set_notify.c @@ -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 */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_event_flags_set_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers an application callback function that is */ +/* called whenever an event flag is set in this group. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block*/ +/* group_put_notify Application callback function */ +/* (TX_NULL disables notify) */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)) +{ + +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + + TX_EVENT_FLAGS_GROUP_NOT_USED(group_ptr); + TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(events_set_notify); + + /* Feature is not enabled, return error. */ + return(TX_FEATURE_NOT_ENABLED); +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Make entry in event log. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET_NOTIFY, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS) + + /* Make entry in event log. */ + TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT + + /* Setup event flag group set notification callback function. */ + group_ptr -> tx_event_flags_group_set_notify = events_set_notify; + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success to caller. */ + return(TX_SUCCESS); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_initialize_high_level.c b/3rd_party/threadx/common/src/tx_initialize_high_level.c new file mode 100644 index 00000000..c7914fc6 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_initialize_high_level.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + +/* Determine if in-line initialization is required. */ +#ifdef TX_INLINE_INITIALIZATION +#define TX_INVOKE_INLINE_INITIALIZATION +#endif + +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_semaphore.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" + + +/* Define the unused memory pointer. The value of the first available + memory address is placed in this variable in the low-level + initialization function. The content of this variable is passed + to the application's system definition function. */ + +VOID *_tx_initialize_unused_memory; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_high_level PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for initializing all of the other */ +/* components in the ThreadX real-time kernel. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_initialize Initialize the thread control */ +/* component */ +/* _tx_timer_initialize Initialize the timer control */ +/* component */ +/* _tx_semaphore_initialize Initialize the semaphore control */ +/* component */ +/* _tx_queue_initialize Initialize the queue control */ +/* component */ +/* _tx_event_flags_initialize Initialize the event flags control*/ +/* component */ +/* _tx_block_pool_initialize Initialize the block pool control */ +/* component */ +/* _tx_byte_pool_initialize Initialize the byte pool control */ +/* component */ +/* _tx_mutex_initialize Initialize the mutex control */ +/* component */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter Kernel entry function */ +/* _tx_initialize_kernel_setup Early kernel setup function that */ +/* is optionally called by */ +/* compiler's startup code. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_initialize_high_level(VOID) +{ + + /* Initialize event tracing, if enabled. */ + TX_TRACE_INITIALIZE + + /* Initialize the event log, if enabled. */ + TX_EL_INITIALIZE + + /* Call the thread control initialization function. */ + _tx_thread_initialize(); + +#ifndef TX_NO_TIMER + + /* Call the timer control initialization function. */ + _tx_timer_initialize(); +#endif + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Call the semaphore initialization function. */ + _tx_semaphore_initialize(); + + /* Call the queue initialization function. */ + _tx_queue_initialize(); + + /* Call the event flag initialization function. */ + _tx_event_flags_initialize(); + + /* Call the block pool initialization function. */ + _tx_block_pool_initialize(); + + /* Call the byte pool initialization function. */ + _tx_byte_pool_initialize(); + + /* Call the mutex initialization function. */ + _tx_mutex_initialize(); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_initialize_kernel_enter.c b/3rd_party/threadx/common/src/tx_initialize_kernel_enter.c new file mode 100644 index 00000000..c18cec37 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_initialize_kernel_enter.c @@ -0,0 +1,150 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/* Define any port-specific scheduling data structures. */ + +TX_PORT_SPECIFIC_DATA + + +#ifdef TX_SAFETY_CRITICAL +TX_SAFETY_CRITICAL_EXCEPTION_HANDLER +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_kernel_enter PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the first ThreadX function called during */ +/* initialization. It is called from the application's "main()" */ +/* function. It is important to note that this routine never */ +/* returns. The processing of this function is relatively simple: */ +/* it calls several ThreadX initialization functions (if needed), */ +/* calls the application define function, and then invokes the */ +/* scheduler. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_initialize_low_level Low-level initialization */ +/* _tx_initialize_high_level High-level initialization */ +/* tx_application_define Application define function */ +/* _tx_thread_scheduler ThreadX scheduling loop */ +/* */ +/* CALLED BY */ +/* */ +/* main Application main program */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_initialize_kernel_enter(VOID) +{ + + /* Determine if the compiler has pre-initialized ThreadX. */ + if (_tx_thread_system_state != TX_INITIALIZE_ALMOST_DONE) + { + + /* No, the initialization still needs to take place. */ + + /* Ensure that the system state variable is set to indicate + initialization is in progress. Note that this variable is + later used to represent interrupt nesting. */ + _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS; + + /* Call any port specific preprocessing. */ + TX_PORT_SPECIFIC_PRE_INITIALIZATION + + /* Invoke the low-level initialization to handle all processor specific + initialization issues. */ + _tx_initialize_low_level(); + + /* Invoke the high-level initialization to exercise all of the + ThreadX components and the application's initialization + function. */ + _tx_initialize_high_level(); + + /* Call any port specific post-processing. */ + TX_PORT_SPECIFIC_POST_INITIALIZATION + } + + /* Optional processing extension. */ + TX_INITIALIZE_KERNEL_ENTER_EXTENSION + + /* Ensure that the system state variable is set to indicate + initialization is in progress. Note that this variable is + later used to represent interrupt nesting. */ + _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS; + + /* Call the application provided initialization function. Pass the + first available memory address to it. */ + tx_application_define(_tx_initialize_unused_memory); + + /* Set the system state in preparation for entering the thread + scheduler. */ + _tx_thread_system_state = TX_INITIALIZE_IS_FINISHED; + + /* Call any port specific pre-scheduler processing. */ + TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION + + /* Enter the scheduling loop to start executing threads! */ + _tx_thread_schedule(); + +#ifdef TX_SAFETY_CRITICAL + + /* If we ever get here, raise safety critical exception. */ + TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_initialize_kernel_setup.c b/3rd_party/threadx/common/src/tx_initialize_kernel_setup.c new file mode 100644 index 00000000..c0923a0c --- /dev/null +++ b/3rd_party/threadx/common/src/tx_initialize_kernel_setup.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_kernel_setup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the compiler's startup code to make */ +/* ThreadX objects accessible to the compiler's library. If this */ +/* function is not called by the compiler, all ThreadX initialization */ +/* takes place from the kernel enter function defined previously. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_initialize_low_level Low-level initialization */ +/* _tx_initialize_high_level High-level initialization */ +/* */ +/* CALLED BY */ +/* */ +/* startup code Compiler startup code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_initialize_kernel_setup(VOID) +{ + + /* Ensure that the system state variable is set to indicate + initialization is in progress. Note that this variable is + later used to represent interrupt nesting. */ + _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS; + + /* Call any port specific preprocessing. */ + TX_PORT_SPECIFIC_PRE_INITIALIZATION + + /* Invoke the low-level initialization to handle all processor specific + initialization issues. */ + _tx_initialize_low_level(); + + /* Invoke the high-level initialization to exercise all of the + ThreadX components and the application's initialization + function. */ + _tx_initialize_high_level(); + + /* Call any port specific post-processing. */ + TX_PORT_SPECIFIC_POST_INITIALIZATION + + /* Set the system state to indicate initialization is almost done. */ + _tx_thread_system_state = TX_INITIALIZE_ALMOST_DONE; +} + diff --git a/3rd_party/threadx/common/src/tx_misra.c b/3rd_party/threadx/common/src/tx_misra.c new file mode 100644 index 00000000..8b8439bc --- /dev/null +++ b/3rd_party/threadx/common/src/tx_misra.c @@ -0,0 +1,836 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** _tx_version_id */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef TX_MISRA_ENABLE +#include "tx_api.h" +#else +#define TX_THREAD_INIT +//CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.1 MISRA C Compliant *"; + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size) +{ + memset(ptr, (INT)value, size); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount) +{ + ptr = ptr + amount; + return(ptr); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount) +{ + ptr = ptr - amount; + return(ptr); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2) +{ + +ULONG value; + + value = (ULONG)(ptr1 - ptr2); + return(value); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr) +{ + return((ULONG) ptr); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount) +{ + ptr = ptr + amount; + return(ptr); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount) +{ + + ptr = ptr - amount; + return(ptr); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2) +{ +ULONG value; + + value = (ULONG)(ptr1 - ptr2); + return(value); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +VOID *_tx_misra_ulong_to_pointer_convert(ULONG input) +{ + + return((VOID *) input); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */ +/** UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, UINT size) +{ + +ULONG *s, *d; +UINT z; + + s = *source; + d = *destination; + z = size; + + *(d) = *(s); + (d)++; + (s)++; + if ((z) > ((UINT) 1)) + { + (z)--; + while ((z)) + { + *(d) = *(s); + (d)++; + (s)++; + (z)--; + } + } + + *source = s; + *destination = d; +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */ +/** TX_TIMER_INTERNAL **ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, TX_TIMER_INTERNAL **ptr2) +{ + +ULONG value; + + value = (ULONG)(ptr1 - ptr2); + return(value); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */ +/** **ptr1, ULONG size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL **ptr1, ULONG amount) +{ + ptr1 = ptr1 + amount; + return(ptr1); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */ +/** *internal_timer, TX_TIMER **user_timer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL *internal_timer, TX_TIMER **user_timer) +{ + +UCHAR *working_ptr; +TX_TIMER *temp_timer; + + + working_ptr = (UCHAR *) internal_timer; + + temp_timer = (TX_TIMER *) working_ptr; + working_ptr = working_ptr - (((UCHAR *) &temp_timer -> tx_timer_internal) - ((UCHAR *) &temp_timer -> tx_timer_id)); + *user_timer = (TX_TIMER *) working_ptr; +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */ +/** VOID **highest_stack); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, VOID **highest_stack) +{ + +TX_INTERRUPT_SAVE_AREA + + TX_DISABLE + if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID)) + { + if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) *highest_stack)) + { + *highest_stack = (thread_ptr) -> tx_thread_stack_ptr; + } + if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) || + (*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) || + (((ULONG *) *highest_stack) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start))) + { + TX_RESTORE + _tx_thread_stack_error_handler((thread_ptr)); + TX_DISABLE + } + if (*(((ULONG *) *highest_stack) - 1) != TX_STACK_FILL) + { + TX_RESTORE + _tx_thread_stack_analyze((thread_ptr)); + TX_DISABLE + } + } + TX_RESTORE +} + + +#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); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +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) +{ + +TX_TRACE_BUFFER_ENTRY *trace_event_ptr; +ULONG trace_system_state; +ULONG trace_priority; +TX_THREAD *trace_thread_ptr; + + + trace_event_ptr = _tx_trace_buffer_current_ptr; + if ((trace_event_ptr) && (_tx_trace_event_enable_bits & ((ULONG) (filter)))) + { + TX_TRACE_PORT_EXTENSION + trace_system_state = (ULONG) _tx_thread_system_state; + trace_thread_ptr = _tx_thread_current_ptr; + + if (trace_system_state == 0) + { + trace_priority = trace_thread_ptr -> tx_thread_priority; + trace_priority = trace_priority | 0x80000000UL | (trace_thread_ptr -> tx_thread_preempt_threshold << 16); + } + else if (trace_system_state < 0xF0F0F0F0UL) + { + trace_priority = (ULONG) trace_thread_ptr; + trace_thread_ptr = (TX_THREAD *) 0xFFFFFFFFUL; + } + else + { + trace_thread_ptr = (TX_THREAD *) 0xF0F0F0F0UL; + trace_priority = 0; + } + trace_event_ptr -> tx_trace_buffer_entry_thread_pointer = (ULONG) trace_thread_ptr; + trace_event_ptr -> tx_trace_buffer_entry_thread_priority = (ULONG) trace_priority; + trace_event_ptr -> tx_trace_buffer_entry_event_id = (ULONG) (event_id); + trace_event_ptr -> tx_trace_buffer_entry_time_stamp = (ULONG) (time_stamp); +#ifdef TX_MISRA_ENABLE + trace_event_ptr -> tx_trace_buffer_entry_info_1 = (ULONG) (info_field_1); + trace_event_ptr -> tx_trace_buffer_entry_info_2 = (ULONG) (info_field_2); + trace_event_ptr -> tx_trace_buffer_entry_info_3 = (ULONG) (info_field_3); + trace_event_ptr -> tx_trace_buffer_entry_info_4 = (ULONG) (info_field_4); +#else + trace_event_ptr -> tx_trace_buffer_entry_information_field_1 = (ULONG) (info_field_1); + trace_event_ptr -> tx_trace_buffer_entry_information_field_2 = (ULONG) (info_field_2); + trace_event_ptr -> tx_trace_buffer_entry_information_field_3 = (ULONG) (info_field_3); + trace_event_ptr -> tx_trace_buffer_entry_information_field_4 = (ULONG) (info_field_4); +#endif + trace_event_ptr++; + if (trace_event_ptr >= _tx_trace_buffer_end_ptr) + { + trace_event_ptr = _tx_trace_buffer_start_ptr; + _tx_trace_buffer_current_ptr = trace_event_ptr; + _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; + if (_tx_trace_full_notify_function) + (_tx_trace_full_notify_function)((VOID *) _tx_trace_header_ptr); + } + else + { + _tx_trace_buffer_current_ptr = trace_event_ptr; + _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; + } + } +} + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_time_stamp_get(VOID); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +ULONG _tx_misra_time_stamp_get(VOID) +{ + + /* Return time stamp. */ + return(0); +} + +#endif + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_always_true(void); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +UINT _tx_misra_always_true(void) +{ + return(TX_TRUE); +} + + +/******************************************************************************************/ +/******************************************************************************************/ +/** */ +/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */ +/** */ +/******************************************************************************************/ +/******************************************************************************************/ +UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr) +{ + + /* Return an indirect UCHAR pointer. */ + return((UCHAR **) ((VOID *) return_ptr)); +} + + +/***************************************************************************************/ +/***************************************************************************************/ +/** */ +/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */ +/** */ +/***************************************************************************************/ +/***************************************************************************************/ +UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer) +{ + + /* Return an indirect UCHAR pointer. */ + return((UCHAR **) ((VOID *) pointer)); +} + + +/***********************************************************************************/ +/***********************************************************************************/ +/** */ +/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */ +/** */ +/***********************************************************************************/ +/***********************************************************************************/ +UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR *) ((VOID *) pool)); +} + + +/******************************************************************************************/ +/******************************************************************************************/ +/** */ +/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */ +/** */ +/******************************************************************************************/ +/******************************************************************************************/ +TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer) +{ + + /* Return a block pool pointer. */ + return((TX_BLOCK_POOL *) ((VOID *) pointer)); +} + + +/*****************************************************************************/ +/*****************************************************************************/ +/** */ +/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */ +/** */ +/*****************************************************************************/ +/*****************************************************************************/ +UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR *) ((VOID *) pointer)); +} + + +/************************************************************************************/ +/************************************************************************************/ +/** */ +/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */ +/** */ +/************************************************************************************/ +/************************************************************************************/ +TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer) +{ + + /* Return a UCHAR pointer. */ + return((TX_BLOCK_POOL *) ((VOID *) pointer)); +} + + +/**************************************************************************************/ +/**************************************************************************************/ +/** */ +/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */ +/** */ +/**************************************************************************************/ +/**************************************************************************************/ +UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR **) ((VOID *) pointer)); +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/** */ +/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */ +/** */ +/*****************************************************************************************/ +/*****************************************************************************************/ +TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer) +{ + + /* Return a byte pool pointer. */ + return((TX_BYTE_POOL *) ((VOID *) pointer)); +} + + +/***************************************************************************************/ +/***************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */ +/** */ +/***************************************************************************************/ +/***************************************************************************************/ +UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR *) ((VOID *) pool)); +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/** */ +/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */ +/** */ +/*****************************************************************************************/ +/*****************************************************************************************/ +ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer) +{ + + /* Return an align time pointer. */ + return((ALIGN_TYPE *) ((VOID *) pointer)); +} + + +/****************************************************************************************************/ +/****************************************************************************************************/ +/** */ +/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */ +/** */ +/****************************************************************************************************/ +/****************************************************************************************************/ +TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer) +{ + + /* Return a byte pool pointer. */ + return((TX_BYTE_POOL **) ((VOID *) pointer)); +} + + +/**************************************************************************************************/ +/**************************************************************************************************/ +/** */ +/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */ +/** */ +/**************************************************************************************************/ +/**************************************************************************************************/ +TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer) +{ + + /* Return event flags pointer. */ + return((TX_EVENT_FLAGS_GROUP *) ((VOID *) pointer)); +} + + +/*****************************************************************************/ +/*****************************************************************************/ +/** */ +/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */ +/** */ +/*****************************************************************************/ +/*****************************************************************************/ +ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer) +{ + + /* Return a ULONG pointer. */ + return((ULONG *) ((VOID *) pointer)); +} + + +/********************************************************************************/ +/********************************************************************************/ +/** */ +/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */ +/** */ +/********************************************************************************/ +/********************************************************************************/ +TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer) +{ + + /* Return a mutex pointer. */ + return((TX_MUTEX *) ((VOID *) pointer)); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_status_get(UINT status); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +UINT _tx_misra_status_get(UINT status) +{ + (VOID)status; + + /* Return a successful status. */ + return(TX_SUCCESS); +} + + +/********************************************************************************/ +/********************************************************************************/ +/** */ +/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */ +/** */ +/********************************************************************************/ +/********************************************************************************/ +TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer) +{ + + /* Return queue pointer. */ + return((TX_QUEUE *) ((VOID *) pointer)); +} + + +/****************************************************************************************/ +/****************************************************************************************/ +/** */ +/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */ +/** */ +/****************************************************************************************/ +/****************************************************************************************/ +TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer) +{ + + /* Return semaphore pointer. */ + return((TX_SEMAPHORE *) ((VOID *) pointer)); +} + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer) +{ + + /* Return a VOID pointer. */ + return((VOID *) ((VOID *) pointer)); +} + + +/*********************************************************************************/ +/*********************************************************************************/ +/** */ +/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */ +/** */ +/*********************************************************************************/ +/*********************************************************************************/ +TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value) +{ + + /* Return a thread pointer. */ + return((TX_THREAD *) ((VOID *) value)); +} + + +/***************************************************************************************************/ +/***************************************************************************************************/ +/** */ +/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */ +/** */ +/***************************************************************************************************/ +/***************************************************************************************************/ +VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer) +{ + + /* Return a void pointer. */ + return((VOID *) ((VOID *) pointer)); +} + + +/***************************************************************************************/ +/***************************************************************************************/ +/** */ +/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */ +/** */ +/***************************************************************************************/ +/***************************************************************************************/ +CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer) +{ + + /* Return a CHAR pointer. */ + return((CHAR *) ((VOID *) pointer)); +} + + +/**********************************************************************************/ +/**********************************************************************************/ +/** */ +/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */ +/** */ +/**********************************************************************************/ +/**********************************************************************************/ +TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer) +{ + + /* Return thread pointer. */ + return((TX_THREAD *) ((VOID *) pointer)); +} + + +#ifdef TX_ENABLE_EVENT_TRACE + +/************************************************************************************************/ +/************************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */ +/** */ +/************************************************************************************************/ +/************************************************************************************************/ +UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR *) ((VOID *) pointer)); +} + + +/************************************************************************************************/ +/************************************************************************************************/ +/** */ +/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */ +/** */ +/************************************************************************************************/ +/************************************************************************************************/ +TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer) +{ + + /* Return an object entry pointer. */ + return((TX_TRACE_OBJECT_ENTRY *) ((VOID *) pointer)); +} + + +/******************************************************************************************/ +/******************************************************************************************/ +/** */ +/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */ +/** */ +/******************************************************************************************/ +/******************************************************************************************/ +TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer) +{ + + /* Return a trace header pointer. */ + return((TX_TRACE_HEADER *) ((VOID *) pointer)); +} + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ +TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer) +{ + + /* Return a trace buffer entry pointer. */ + return((TX_TRACE_BUFFER_ENTRY *) ((VOID *) pointer)); +} + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ +UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR *) ((VOID *) pointer)); +} + +#endif + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ +UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) +{ + + /* Return a UCHAR pointer. */ + return((UCHAR *) ((VOID *) pointer)); +} + + +#endif + diff --git a/3rd_party/threadx/common/src/tx_mutex_cleanup.c b/3rd_party/threadx/common/src/tx_mutex_cleanup.c new file mode 100644 index 00000000..ec62600e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_cleanup.c @@ -0,0 +1,317 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_cleanup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes mutex timeout and thread terminate */ +/* actions that require the mutex data structures to be cleaned */ +/* up. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to suspended thread's */ +/* control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_timeout Thread timeout processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* _tx_thread_wait_abort Thread wait abort processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) +{ + +#ifndef TX_NOT_INTERRUPTABLE +TX_INTERRUPT_SAVE_AREA +#endif + +TX_MUTEX *mutex_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts to remove the suspended thread from the mutex. */ + TX_DISABLE + + /* Determine if the cleanup is still required. */ + if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_mutex_cleanup)) + { + + /* Check for valid suspension sequence. */ + if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) + { + + /* Setup pointer to mutex control block. */ + mutex_ptr = TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); + + /* Check for NULL mutex pointer. */ + if (mutex_ptr != TX_NULL) + { + + /* Determine if the mutex ID is valid. */ + if (mutex_ptr -> tx_mutex_id == TX_MUTEX_ID) + { + + /* Determine if there are any thread suspensions. */ + if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS) + { +#else + + /* Setup pointer to mutex control block. */ + mutex_ptr = TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); +#endif + + /* Yes, we still have thread suspension! */ + + /* Clear the suspension cleanup flag. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Decrement the suspension count. */ + mutex_ptr -> tx_mutex_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = mutex_ptr -> tx_mutex_suspended_count; + + /* Remove the suspended thread from the list. */ + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + mutex_ptr -> tx_mutex_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same suspension list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Determine if we need to update the head pointer. */ + if (mutex_ptr -> tx_mutex_suspension_list == thread_ptr) + { + + /* Update the list head pointer. */ + mutex_ptr -> tx_mutex_suspension_list = next_thread; + } + } + + /* Now we need to determine if this cleanup is from a terminate, timeout, + or from a wait abort. */ + if (thread_ptr -> tx_thread_state == TX_MUTEX_SUSP) + { + + /* Timeout condition and the thread still suspended on the mutex. + Setup return error status and resume the thread. */ + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Increment the total timeouts counter. */ + _tx_mutex_performance_timeout_count++; + + /* Increment the number of timeouts on this semaphore. */ + mutex_ptr -> tx_mutex_performance_timeout_count++; +#endif + + /* Setup return status. */ + thread_ptr -> tx_thread_suspend_status = TX_NOT_AVAILABLE; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread! */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } +#ifndef TX_NOT_INTERRUPTABLE + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_thread_release PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function releases all mutexes owned by the thread. This */ +/* function is called when the thread completes or is terminated. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread's control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_put Release the mutex */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_shell_entry Thread completion processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_mutex_thread_release(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_MUTEX *mutex_ptr; +#ifdef TX_MISRA_ENABLE +UINT status; +#endif + + + /* Disable interrupts. */ + TX_DISABLE + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Loop to look at all the mutexes. */ + do + { + + /* Pickup the mutex head pointer. */ + mutex_ptr = thread_ptr -> tx_thread_owned_mutex_list; + + /* Determine if there is a mutex. */ + if (mutex_ptr != TX_NULL) + { + + /* Yes, set the ownership count to 1. */ + mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1); + + /* Restore interrupts. */ + TX_RESTORE + +#ifdef TX_MISRA_ENABLE + /* Release the mutex. */ + do + { + status = _tx_mutex_put(mutex_ptr); + } while (status != TX_SUCCESS); +#else + _tx_mutex_put(mutex_ptr); +#endif + + /* Disable interrupts. */ + TX_DISABLE + + /* Move to the next mutex. */ + mutex_ptr = thread_ptr -> tx_thread_owned_mutex_list; + } + } while (mutex_ptr != TX_NULL); + + /* Restore preemption. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_create.c b/3rd_party/threadx/common/src/tx_mutex_create.c new file mode 100644 index 00000000..a811df87 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_create.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_trace.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a mutex with optional priority inheritance as */ +/* specified in this call. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block*/ +/* name_ptr Pointer to mutex name */ +/* inherit Priority inheritance option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_MUTEX *next_mutex; +TX_MUTEX *previous_mutex; + + + /* Initialize mutex control block to all zeros. */ + TX_MEMSET(mutex_ptr, 0, (sizeof(TX_MUTEX))); + + /* Setup the basic mutex fields. */ + mutex_ptr -> tx_mutex_name = name_ptr; + mutex_ptr -> tx_mutex_inherit = inherit; + + /* Disable interrupts to place the mutex on the created list. */ + TX_DISABLE + + /* Setup the mutex ID to make it valid. */ + mutex_ptr -> tx_mutex_id = TX_MUTEX_ID; + + /* Setup the thread mutex release function pointer. */ + _tx_thread_mutex_release = &(_tx_mutex_thread_release); + + /* Place the mutex on the list of created mutexes. First, + check for an empty list. */ + if (_tx_mutex_created_count == TX_EMPTY) + { + + /* The created mutex list is empty. Add mutex to empty list. */ + _tx_mutex_created_ptr = mutex_ptr; + mutex_ptr -> tx_mutex_created_next = mutex_ptr; + mutex_ptr -> tx_mutex_created_previous = mutex_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_mutex = _tx_mutex_created_ptr; + previous_mutex = next_mutex -> tx_mutex_created_previous; + + /* Place the new mutex in the list. */ + next_mutex -> tx_mutex_created_previous = mutex_ptr; + previous_mutex -> tx_mutex_created_next = mutex_ptr; + + /* Setup this mutex's next and previous created links. */ + mutex_ptr -> tx_mutex_created_previous = previous_mutex; + mutex_ptr -> tx_mutex_created_next = next_mutex; + } + + /* Increment the ownership count. */ + _tx_mutex_created_count++; + + /* Optional mutex create extended processing. */ + TX_MUTEX_CREATE_EXTENSION(mutex_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, name_ptr, inherit, 0) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_CREATE, mutex_ptr, inherit, TX_POINTER_TO_ULONG_CONVERT(&next_mutex), 0, TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_CREATE_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_delete.c b/3rd_party/threadx/common/src/tx_mutex_delete.c new file mode 100644 index 00000000..76a4441f --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_delete.c @@ -0,0 +1,245 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified mutex. All threads */ +/* suspended on the mutex are resumed with the TX_DELETED status */ +/* code. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_put Release an owned mutex */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +TX_THREAD *owner_thread; +UINT suspended_count; +TX_MUTEX *next_mutex; +TX_MUTEX *previous_mutex; +#ifdef TX_MISRA_ENABLE +UINT status; +#endif + + /* Disable interrupts to remove the mutex from the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_DELETE, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_MUTEX_EVENTS) + + /* Optional mutex delete extended processing. */ + TX_MUTEX_DELETE_EXTENSION(mutex_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(mutex_ptr) + + /* Log this kernel call. */ + TX_EL_MUTEX_DELETE_INSERT + + /* Clear the mutex ID to make it invalid. */ + mutex_ptr -> tx_mutex_id = TX_CLEAR_ID; + + /* Decrement the created count. */ + _tx_mutex_created_count--; + + /* See if the mutex is the only one on the list. */ + if (_tx_mutex_created_count == TX_EMPTY) + { + + /* Only created mutex, just set the created list to NULL. */ + _tx_mutex_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_mutex = mutex_ptr -> tx_mutex_created_next; + previous_mutex = mutex_ptr -> tx_mutex_created_previous; + next_mutex -> tx_mutex_created_previous = previous_mutex; + previous_mutex -> tx_mutex_created_next = next_mutex; + + /* See if we have to update the created list head pointer. */ + if (_tx_mutex_created_ptr == mutex_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_mutex_created_ptr = next_mutex; + } + } + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Pickup the suspension information. */ + thread_ptr = mutex_ptr -> tx_mutex_suspension_list; + mutex_ptr -> tx_mutex_suspension_list = TX_NULL; + suspended_count = mutex_ptr -> tx_mutex_suspended_count; + mutex_ptr -> tx_mutex_suspended_count = TX_NO_SUSPENSIONS; + + + /* Determine if the mutex is currently on a thread's ownership list. */ + + /* Setup pointer to owner of mutex. */ + owner_thread = mutex_ptr -> tx_mutex_owner; + + /* Determine if there is a valid thread pointer. */ + if (owner_thread != TX_NULL) + { + + /* Yes, remove this mutex from the owned list. */ + + /* Set the ownership count to 1. */ + mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1); + + /* Restore interrupts. */ + TX_RESTORE + +#ifdef TX_MISRA_ENABLE + /* Release the mutex. */ + do + { + status = _tx_mutex_put(mutex_ptr); + } while (status != TX_SUCCESS); +#else + _tx_mutex_put(mutex_ptr); +#endif + + /* Disable interrupts. */ + TX_DISABLE + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the mutex list to resume any and all threads suspended + on this mutex. */ + while (suspended_count != ((ULONG) 0)) + { + + /* Decrement the suspension count. */ + suspended_count--; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_DELETED. */ + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + + /* Move the thread pointer ahead. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move to next thread. */ + thread_ptr = next_thread; + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_MUTEX_DELETE_PORT_COMPLETION(mutex_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Release previous preempt disable. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_get.c b/3rd_party/threadx/common/src/tx_mutex_get.c new file mode 100644 index 00000000..d5c9a077 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_get.c @@ -0,0 +1,411 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the specified mutex. If the calling thread */ +/* already owns the mutex, an ownership count is simply increased. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Suspend thread service */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* _tx_mutex_priority_change Inherit thread priority */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_MUTEX *next_mutex; +TX_MUTEX *previous_mutex; +TX_THREAD *mutex_owner; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; + + + /* Disable interrupts to get an instance from the mutex. */ + TX_DISABLE + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Increment the total mutex get counter. */ + _tx_mutex_performance_get_count++; + + /* Increment the number of attempts to get this mutex. */ + mutex_ptr -> tx_mutex_performance_get_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_GET, mutex_ptr, wait_option, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_GET_INSERT + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Determine if this mutex is available. */ + if (mutex_ptr -> tx_mutex_ownership_count == ((UINT) 0)) + { + + /* Set the ownership count to 1. */ + mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1); + + /* Remember that the calling thread owns the mutex. */ + mutex_ptr -> tx_mutex_owner = thread_ptr; + + /* Determine if the thread pointer is valid. */ + if (thread_ptr != TX_NULL) + { + + /* Determine if priority inheritance is required. */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Remember the current priority of thread. */ + mutex_ptr -> tx_mutex_original_priority = thread_ptr -> tx_thread_priority; + + /* Setup the highest priority waiting thread. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = ((UINT) TX_MAX_PRIORITIES); + } + + /* Pickup next mutex pointer, which is the head of the list. */ + next_mutex = thread_ptr -> tx_thread_owned_mutex_list; + + /* Determine if this thread owns any other mutexes that have priority inheritance. */ + if (next_mutex != TX_NULL) + { + + /* Non-empty list. Link up the mutex. */ + + /* Pickup the next and previous mutex pointer. */ + previous_mutex = next_mutex -> tx_mutex_owned_previous; + + /* Place the owned mutex in the list. */ + next_mutex -> tx_mutex_owned_previous = mutex_ptr; + previous_mutex -> tx_mutex_owned_next = mutex_ptr; + + /* Setup this mutex's next and previous created links. */ + mutex_ptr -> tx_mutex_owned_previous = previous_mutex; + mutex_ptr -> tx_mutex_owned_next = next_mutex; + } + else + { + + /* The owned mutex list is empty. Add mutex to empty list. */ + thread_ptr -> tx_thread_owned_mutex_list = mutex_ptr; + mutex_ptr -> tx_mutex_owned_next = mutex_ptr; + mutex_ptr -> tx_mutex_owned_previous = mutex_ptr; + } + + /* Increment the number of mutexes owned counter. */ + thread_ptr -> tx_thread_owned_mutex_count++; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success. */ + status = TX_SUCCESS; + } + + /* Otherwise, see if the owning thread is trying to obtain the same mutex. */ + else if (mutex_ptr -> tx_mutex_owner == thread_ptr) + { + + /* The owning thread is requesting the mutex again, just + increment the ownership count. */ + mutex_ptr -> tx_mutex_ownership_count++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success. */ + status = TX_SUCCESS; + } + else + { + + /* Determine if the request specifies suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_NOT_AVAILABLE; + } + else + { + + /* Prepare for suspension of this thread. */ + + /* Pickup the mutex owner. */ + mutex_owner = mutex_ptr -> tx_mutex_owner; + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Increment the total mutex suspension counter. */ + _tx_mutex_performance_suspension_count++; + + /* Increment the number of suspensions on this mutex. */ + mutex_ptr -> tx_mutex_performance_suspension_count++; + + /* Determine if a priority inversion is present. */ + if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_priority) + { + + /* Yes, priority inversion is present! */ + + /* Increment the total mutex priority inversions counter. */ + _tx_mutex_performance_priority_inversion_count++; + + /* Increment the number of priority inversions on this mutex. */ + mutex_ptr -> tx_mutex_performance_priority_inversion_count++; + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the number of total thread priority inversions. */ + _tx_thread_performance_priority_inversion_count++; + + /* Increment the number of priority inversions for this thread. */ + thread_ptr -> tx_thread_performance_priority_inversion_count++; +#endif + } +#endif + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_mutex_cleanup); + + /* Setup cleanup information, i.e. this mutex control + block. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) mutex_ptr; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Setup suspension list. */ + if (mutex_ptr -> tx_mutex_suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + mutex_ptr -> tx_mutex_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = mutex_ptr -> tx_mutex_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Increment the suspension count. */ + mutex_ptr -> tx_mutex_suspended_count++; + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_MUTEX_SUSP; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Determine if we need to raise the priority of the thread + owning the mutex. */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Determine if this is the highest priority to raise for this mutex. */ + if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority) + { + + /* Remember this priority. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = thread_ptr -> tx_thread_priority; + } + + /* Determine if we have to update inherit priority level of the mutex owner. */ + if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority) + { + + /* Remember the new priority inheritance priority. */ + mutex_owner -> tx_thread_inherit_priority = thread_ptr -> tx_thread_priority; + } + + /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority. */ + if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority) + { + + /* Yes, raise the suspended, owning thread's priority to that + of the current thread. */ + _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority); + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Increment the total mutex priority inheritance counter. */ + _tx_mutex_performance__priority_inheritance_count++; + + /* Increment the number of priority inheritance situations on this mutex. */ + mutex_ptr -> tx_mutex_performance__priority_inheritance_count++; +#endif + } + } + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if we need to raise the priority of the thread + owning the mutex. */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Determine if this is the highest priority to raise for this mutex. */ + if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority) + { + + /* Remember this priority. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = thread_ptr -> tx_thread_priority; + } + + /* Determine if we have to update inherit priority level of the mutex owner. */ + if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority) + { + + /* Remember the new priority inheritance priority. */ + mutex_owner -> tx_thread_inherit_priority = thread_ptr -> tx_thread_priority; + } + + /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority. */ + if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority) + { + + /* Yes, raise the suspended, owning thread's priority to that + of the current thread. */ + _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority); + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Increment the total mutex priority inheritance counter. */ + _tx_mutex_performance__priority_inheritance_count++; + + /* Increment the number of priority inheritance situations on this mutex. */ + mutex_ptr -> tx_mutex_performance__priority_inheritance_count++; +#endif + } + } + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Immediate return, return error completion. */ + status = TX_NOT_AVAILABLE; + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_info_get.c b/3rd_party/threadx/common/src/tx_mutex_info_get.c new file mode 100644 index 00000000..b28f9479 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_info_get.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified mutex. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* name Destination for the mutex name */ +/* count Destination for the owner count */ +/* owner Destination for the owner's */ +/* thread control block pointer */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on the mutex */ +/* suspended_count Destination for suspended count */ +/* next_mutex Destination for pointer to next */ +/* mutex on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, + TX_THREAD **first_suspended, ULONG *suspended_count, + TX_MUTEX **next_mutex) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the mutex. */ + if (name != TX_NULL) + { + + *name = mutex_ptr -> tx_mutex_name; + } + + /* Retrieve the current ownership count of the mutex. */ + if (count != TX_NULL) + { + + *count = ((ULONG) mutex_ptr -> tx_mutex_ownership_count); + } + + /* Retrieve the current owner of the mutex. */ + if (owner != TX_NULL) + { + + *owner = mutex_ptr -> tx_mutex_owner; + } + + /* Retrieve the first thread suspended on this mutex. */ + if (first_suspended != TX_NULL) + { + + *first_suspended = mutex_ptr -> tx_mutex_suspension_list; + } + + /* Retrieve the number of threads suspended on this mutex. */ + if (suspended_count != TX_NULL) + { + + *suspended_count = (ULONG) mutex_ptr -> tx_mutex_suspended_count; + } + + /* Retrieve the pointer to the next mutex created. */ + if (next_mutex != TX_NULL) + { + + *next_mutex = mutex_ptr -> tx_mutex_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_initialize.c b/3rd_party/threadx/common/src/tx_mutex_initialize.c new file mode 100644 index 00000000..941912b3 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_initialize.c @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_mutex.h" + + +#ifndef TX_INLINE_INITIALIZATION + +/* Locate mutex component data in this file. */ + +/* Define the head pointer of the created mutex list. */ + +TX_MUTEX * _tx_mutex_created_ptr; + + +/* Define the variable that holds the number of created mutexes. */ + +ULONG _tx_mutex_created_count; + + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + +/* Define the total number of mutex puts. */ + +ULONG _tx_mutex_performance_put_count; + + +/* Define the total number of mutex gets. */ + +ULONG _tx_mutex_performance_get_count; + + +/* Define the total number of mutex suspensions. */ + +ULONG _tx_mutex_performance_suspension_count; + + +/* Define the total number of mutex timeouts. */ + +ULONG _tx_mutex_performance_timeout_count; + + +/* Define the total number of priority inversions. */ + +ULONG _tx_mutex_performance_priority_inversion_count; + + +/* Define the total number of priority inheritance conditions. */ + +ULONG _tx_mutex_performance__priority_inheritance_count; + +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the mutex component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* opt out of function when */ +/* TX_INLINE_INITIALIZATION is */ +/* defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_mutex_initialize(VOID) +{ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created mutexes list and the + number of mutexes created. */ + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = TX_EMPTY; + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Initialize the mutex performance counters. */ + _tx_mutex_performance_put_count = ((ULONG) 0); + _tx_mutex_performance_get_count = ((ULONG) 0); + _tx_mutex_performance_suspension_count = ((ULONG) 0); + _tx_mutex_performance_timeout_count = ((ULONG) 0); + _tx_mutex_performance_priority_inversion_count = ((ULONG) 0); + _tx_mutex_performance__priority_inheritance_count = ((ULONG) 0); +#endif +#endif +} +#endif diff --git a/3rd_party/threadx/common/src/tx_mutex_performance_info_get.c b/3rd_party/threadx/common/src/tx_mutex_performance_info_get.c new file mode 100644 index 00000000..7bd0512e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_performance_info_get.c @@ -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 */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_mutex.h" +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* mutex. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* puts Destination for the number of */ +/* puts on to this mutex */ +/* gets Destination for the number of */ +/* gets on this mutex */ +/* suspensions Destination for the number of */ +/* suspensions on this mutex */ +/* timeouts Destination for number of timeouts*/ +/* on this mutex */ +/* inversions Destination for number of priority*/ +/* inversions on this mutex */ +/* inheritances Destination for number of priority*/ +/* inheritances on this mutex */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets, + ULONG *suspensions, ULONG *timeouts, ULONG *inversions, ULONG *inheritances) +{ + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Determine if this is a legal request. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the mutex ID is invalid. */ + else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Mutex pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PERFORMANCE_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the number of puts on this mutex. */ + if (puts != TX_NULL) + { + + *puts = mutex_ptr -> tx_mutex_performance_put_count; + } + + /* Retrieve the number of gets on this mutex. */ + if (gets != TX_NULL) + { + + *gets = mutex_ptr -> tx_mutex_performance_get_count; + } + + /* Retrieve the number of suspensions on this mutex. */ + if (suspensions != TX_NULL) + { + + *suspensions = mutex_ptr -> tx_mutex_performance_suspension_count; + } + + /* Retrieve the number of timeouts on this mutex. */ + if (timeouts != TX_NULL) + { + + *timeouts = mutex_ptr -> tx_mutex_performance_timeout_count; + } + + /* Retrieve the number of priority inversions on this mutex. */ + if (inversions != TX_NULL) + { + + *inversions = mutex_ptr -> tx_mutex_performance_priority_inversion_count; + } + + /* Retrieve the number of priority inheritances on this mutex. */ + if (inheritances != TX_NULL) + { + + *inheritances = mutex_ptr -> tx_mutex_performance__priority_inheritance_count; + } + + /* Restore interrupts. */ + TX_RESTORE + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (mutex_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (puts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (gets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (inversions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (inheritances != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_mutex_performance_system_info_get.c new file mode 100644 index 00000000..04409e7b --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_performance_system_info_get.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_mutex.h" +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves system mutex performance information. */ +/* */ +/* INPUT */ +/* */ +/* puts Destination for total number of */ +/* mutex puts */ +/* gets Destination for total number of */ +/* mutex gets */ +/* suspensions Destination for total number of */ +/* mutex suspensions */ +/* timeouts Destination for total number of */ +/* mutex timeouts */ +/* inversions Destination for total number of */ +/* mutex priority inversions */ +/* inheritances Destination for total number of */ +/* mutex priority inheritances */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions, + ULONG *timeouts, ULONG *inversions, ULONG *inheritances) +{ + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the total number of mutex puts. */ + if (puts != TX_NULL) + { + + *puts = _tx_mutex_performance_put_count; + } + + /* Retrieve the total number of mutex gets. */ + if (gets != TX_NULL) + { + + *gets = _tx_mutex_performance_get_count; + } + + /* Retrieve the total number of mutex suspensions. */ + if (suspensions != TX_NULL) + { + + *suspensions = _tx_mutex_performance_suspension_count; + } + + /* Retrieve the total number of mutex timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_mutex_performance_timeout_count; + } + + /* Retrieve the total number of mutex priority inversions. */ + if (inversions != TX_NULL) + { + + *inversions = _tx_mutex_performance_priority_inversion_count; + } + + /* Retrieve the total number of mutex priority inheritances. */ + if (inheritances != TX_NULL) + { + + *inheritances = _tx_mutex_performance__priority_inheritance_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (puts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (gets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (inversions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (inheritances != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_prioritize.c b/3rd_party/threadx/common/src/tx_mutex_prioritize.c new file mode 100644 index 00000000..3aae0e18 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_prioritize.c @@ -0,0 +1,267 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the highest priority suspended thread at the */ +/* front of the suspension list. All other threads remain in the same */ +/* FIFO suspension order. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_prioritize(TX_MUTEX *mutex_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *priority_thread_ptr; +TX_THREAD *head_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT list_changed; +#ifdef TX_MISRA_ENABLE +UINT status; +#endif + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PRIORITIZE, mutex_ptr, mutex_ptr -> tx_mutex_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_PRIORITIZE_INSERT + + /* Pickup the suspended count. */ + suspended_count = mutex_ptr -> tx_mutex_suspended_count; + + /* Determine if there are fewer than 2 suspended threads. */ + if (suspended_count < ((UINT) 2)) + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Determine if there how many threads are suspended on this mutex. */ + else if (suspended_count == ((UINT) 2)) + { + + /* Pickup the head pointer and the next pointer. */ + head_ptr = mutex_ptr -> tx_mutex_suspension_list; + next_thread = head_ptr -> tx_thread_suspended_next; + + /* Determine if the next suspended thread has a higher priority. */ + if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) + { + + /* Yes, move the list head to the next thread. */ + mutex_ptr -> tx_mutex_suspension_list = next_thread; + } + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = mutex_ptr -> tx_mutex_suspension_list; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Set the list changed flag to false. */ + list_changed = TX_FALSE; + + /* Search through the list to find the highest priority thread. */ + do + { + + /* Is the current thread higher priority? */ + if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) + { + + /* Yes, remember that this thread is the highest priority. */ + priority_thread_ptr = thread_ptr; + } + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Determine if any changes to the list have occurred while + interrupts were enabled. */ + + /* Is the list head the same? */ + if (head_ptr != mutex_ptr -> tx_mutex_suspension_list) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + else + { + + /* Is the suspended count the same? */ + if (suspended_count != mutex_ptr -> tx_mutex_suspended_count) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + } + + /* Determine if the list has changed. */ + if (list_changed == TX_FALSE) + { + + /* Move the thread pointer to the next thread. */ + thread_ptr = thread_ptr -> tx_thread_suspended_next; + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = mutex_ptr -> tx_mutex_suspension_list; + suspended_count = mutex_ptr -> tx_mutex_suspended_count; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Reset the list changed flag. */ + list_changed = TX_FALSE; + } + + } while (thread_ptr != head_ptr); + + /* Release preemption. */ + _tx_thread_preempt_disable--; + + /* Now determine if the highest priority thread is at the front + of the list. */ + if (priority_thread_ptr != head_ptr) + { + + /* No, we need to move the highest priority suspended thread to the + front of the list. */ + + /* First, remove the highest priority thread by updating the + adjacent suspended threads. */ + next_thread = priority_thread_ptr -> tx_thread_suspended_next; + previous_thread = priority_thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Now, link the highest priority thread at the front of the list. */ + previous_thread = head_ptr -> tx_thread_suspended_previous; + priority_thread_ptr -> tx_thread_suspended_next = head_ptr; + priority_thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = priority_thread_ptr; + head_ptr -> tx_thread_suspended_previous = priority_thread_ptr; + + /* Move the list head pointer to the highest priority suspended thread. */ + mutex_ptr -> tx_mutex_suspension_list = priority_thread_ptr; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + +#ifdef TX_MISRA_ENABLE + + /* Initialize status to success. */ + status = TX_SUCCESS; + + /* Define extended processing option. */ + status = TX_MUTEX_PRIORITIZE_MISRA_EXTENSION(status); + + /* Return completion status. */ + return(status); +#else + + /* Return successful completion. */ + return(TX_SUCCESS); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_priority_change.c b/3rd_party/threadx/common/src/tx_mutex_priority_change.c new file mode 100644 index 00000000..d4945d83 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_priority_change.c @@ -0,0 +1,339 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_priority_change PORTABLE C */ +/* 6.1.6 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the priority of the specified thread for the */ +/* priority inheritance option of the mutex service. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* new_priority New thread priority */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_thread_system_suspend Suspend thread */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_mutex_get Inherit priority */ +/* _tx_mutex_put Restore previous priority */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 William E. Lamie Modified comment(s), and */ +/* change thread state from */ +/* TX_SUSPENDED to */ +/* TX_PRIORITY_CHANGE before */ +/* calling */ +/* _tx_thread_system_suspend, */ +/* resulting in version 6.1 */ +/* 04-02-2021 Scott Larson Modified comments, fixed */ +/* mapping current thread's */ +/* priority rather than next, */ +/* resulting in version 6.1.6 */ +/* */ +/**************************************************************************/ +VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority) +{ + +#ifndef TX_NOT_INTERRUPTABLE + +TX_INTERRUPT_SAVE_AREA +#endif + +TX_THREAD *execute_ptr; +TX_THREAD *next_execute_ptr; +UINT original_priority; +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +ULONG priority_bit; +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif +#endif + + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Lockout interrupts while the thread is being suspended. */ + TX_DISABLE +#endif + + /* Determine if this thread is currently ready. */ + if (thread_ptr -> tx_thread_state != TX_READY) + { + + /* Change thread priority to the new mutex priority-inheritance priority. */ + thread_ptr -> tx_thread_priority = new_priority; + + /* Determine how to setup the thread's preemption-threshold. */ + if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) + { + + /* Change thread preemption-threshold to the user's preemption-threshold. */ + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold; + } + else + { + + /* Change the thread preemption-threshold to the new threshold. */ + thread_ptr -> tx_thread_preempt_threshold = new_priority; + } + +#ifndef TX_NOT_INTERRUPTABLE + /* Restore interrupts. */ + TX_RESTORE +#endif + } + else + { + + /* Pickup the next thread to execute. */ + execute_ptr = _tx_thread_execute_ptr; + + /* Save the original priority. */ + original_priority = thread_ptr -> tx_thread_priority; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Set the state to priority change. */ + thread_ptr -> tx_thread_state = TX_PRIORITY_CHANGE; + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); + + /* At this point, the preempt disable flag is still set, so we still have + protection against all preemption. */ + + /* Change thread priority to the new mutex priority-inheritance priority. */ + thread_ptr -> tx_thread_priority = new_priority; + + /* Determine how to setup the thread's preemption-threshold. */ + if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) + { + + /* Change thread preemption-threshold to the user's preemption-threshold. */ + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold; + } + else + { + + /* Change the thread preemption-threshold to the new threshold. */ + thread_ptr -> tx_thread_preempt_threshold = new_priority; + } + + /* Resume the thread with the new priority. */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; +#else + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable = _tx_thread_preempt_disable + ((UINT) 2); + + /* Set the state to priority change. */ + thread_ptr -> tx_thread_state = TX_PRIORITY_CHANGE; + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0); + + /* Restore interrupts. */ + TX_RESTORE + + /* The thread is ready and must first be removed from the list. Call the + system suspend function to accomplish this. */ + _tx_thread_system_suspend(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE + + /* At this point, the preempt disable flag is still set, so we still have + protection against all preemption. */ + + /* Change thread priority to the new mutex priority-inheritance priority. */ + thread_ptr -> tx_thread_priority = new_priority; + + /* Determine how to setup the thread's preemption-threshold. */ + if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) + { + + /* Change thread preemption-threshold to the user's preemption-threshold. */ + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold; + } + else + { + + /* Change the thread preemption-threshold to the new threshold. */ + thread_ptr -> tx_thread_preempt_threshold = new_priority; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread with the new priority. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Optional processing extension. */ + TX_MUTEX_PRIORITY_CHANGE_EXTENSION + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts. */ + TX_DISABLE +#endif + + /* Pickup the next thread to execute. */ + next_execute_ptr = _tx_thread_execute_ptr; + + /* Determine if this thread is not the next thread to execute. */ + if (thread_ptr != next_execute_ptr) + { + + /* Make sure the thread is still ready. */ + if (thread_ptr -> tx_thread_state == TX_READY) + { + + /* Now check and see if this thread has an equal or higher priority. */ + if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority) + { + + /* Now determine if this thread was the previously executing thread. */ + if (thread_ptr == execute_ptr) + { + + /* Yes, this thread was previously executing before we temporarily suspended and resumed + it in order to change the priority. A lower or same priority thread cannot be the next thread + to execute in this case since this thread really didn't suspend. Simply reset the execute + pointer to this thread. */ + _tx_thread_execute_ptr = thread_ptr; + + /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */ + if (original_priority < new_priority) + { + + /* Ensure that this thread is placed at the front of the priority list. */ + _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr; + } + } + } + else + { + + /* Now determine if this thread's preemption-threshold needs to be enforced. */ + if (thread_ptr -> tx_thread_preempt_threshold < thread_ptr -> tx_thread_priority) + { + + /* Yes, preemption-threshold is in force for this thread. */ + + /* Compare the next thread to execute thread's priority against the thread's preemption-threshold. */ + if (thread_ptr -> tx_thread_preempt_threshold <= next_execute_ptr -> tx_thread_priority) + { + + /* We must swap execute pointers to enforce the preemption-threshold of a thread coming out of + priority inheritance. */ + _tx_thread_execute_ptr = thread_ptr; + + /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */ + if (original_priority < new_priority) + { + + /* Ensure that this thread is placed at the front of the priority list. */ + _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr; + } + } + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + else + { + + /* In this case, we need to mark the preempted map to indicate a thread executed above the + preemption-threshold. */ + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = (thread_ptr -> tx_thread_priority)/ ((UINT) 32); + + /* Set the active bit to remember that the preempt map has something set. */ + TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit; +#endif + + /* Remember that this thread was preempted by a thread above the thread's threshold. */ + TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; + } +#endif + } + } + } + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE +#endif + } +} + diff --git a/3rd_party/threadx/common/src/tx_mutex_put.c b/3rd_party/threadx/common/src/tx_mutex_put.c new file mode 100644 index 00000000..46b4c29f --- /dev/null +++ b/3rd_party/threadx/common/src/tx_mutex_put.c @@ -0,0 +1,656 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_put PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function puts back an instance of the specified mutex. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Success completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_mutex_priority_change Restore previous thread priority */ +/* _tx_mutex_prioritize Prioritize the mutex suspension */ +/* _tx_mutex_thread_release Release all thread's mutexes */ +/* _tx_mutex_delete Release ownership upon mutex */ +/* deletion */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_mutex_put(TX_MUTEX *mutex_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *old_owner; +UINT old_priority; +UINT status; +TX_MUTEX *next_mutex; +TX_MUTEX *previous_mutex; +UINT owned_count; +UINT suspended_count; +TX_THREAD *current_thread; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +TX_THREAD *suspended_thread; +UINT inheritance_priority; + + + /* Setup status to indicate the processing is not complete. */ + status = TX_NOT_DONE; + + /* Disable interrupts to put an instance back to the mutex. */ + TX_DISABLE + +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + + /* Increment the total mutex put counter. */ + _tx_mutex_performance_put_count++; + + /* Increment the number of attempts to put this mutex. */ + mutex_ptr -> tx_mutex_performance_put_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PUT, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_POINTER_TO_ULONG_CONVERT(&old_priority), TX_TRACE_MUTEX_EVENTS) + + /* Log this kernel call. */ + TX_EL_MUTEX_PUT_INSERT + + /* Determine if this mutex is owned. */ + if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0)) + { + + /* Pickup the owning thread pointer. */ + thread_ptr = mutex_ptr -> tx_mutex_owner; + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Check to see if the mutex is owned by the calling thread. */ + if (mutex_ptr -> tx_mutex_owner != current_thread) + { + + /* Determine if the preempt disable flag is set, indicating that + the caller is not the application but from ThreadX. In such + cases, the thread mutex owner does not need to match. */ + if (_tx_thread_preempt_disable == ((UINT) 0)) + { + + /* Invalid mutex release. */ + + /* Restore interrupts. */ + TX_RESTORE + + /* Caller does not own the mutex. */ + status = TX_NOT_OWNED; + } + } + + /* Determine if we should continue. */ + if (status == TX_NOT_DONE) + { + + /* Decrement the mutex ownership count. */ + mutex_ptr -> tx_mutex_ownership_count--; + + /* Determine if the mutex is still owned by the current thread. */ + if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Mutex is still owned, just return successful status. */ + status = TX_SUCCESS; + } + else + { + + /* Check for a NULL thread pointer, which can only happen during initialization. */ + if (thread_ptr == TX_NULL) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Mutex is now available, return successful status. */ + status = TX_SUCCESS; + } + else + { + + /* The mutex is now available. */ + + /* Remove this mutex from the owned mutex list. */ + + /* Decrement the ownership count. */ + thread_ptr -> tx_thread_owned_mutex_count--; + + /* Determine if this mutex was the only one on the list. */ + if (thread_ptr -> tx_thread_owned_mutex_count == ((UINT) 0)) + { + + /* Yes, the list is empty. Simply set the head pointer to NULL. */ + thread_ptr -> tx_thread_owned_mutex_list = TX_NULL; + } + else + { + + /* No, there are more mutexes on the list. */ + + /* Link-up the neighbors. */ + next_mutex = mutex_ptr -> tx_mutex_owned_next; + previous_mutex = mutex_ptr -> tx_mutex_owned_previous; + next_mutex -> tx_mutex_owned_previous = previous_mutex; + previous_mutex -> tx_mutex_owned_next = next_mutex; + + /* See if we have to update the created list head pointer. */ + if (thread_ptr -> tx_thread_owned_mutex_list == mutex_ptr) + { + + /* Yes, move the head pointer to the next link. */ + thread_ptr -> tx_thread_owned_mutex_list = next_mutex; + } + } + + /* Determine if the simple, non-suspension, non-priority inheritance case is present. */ + if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) + { + + /* Is this a priority inheritance mutex? */ + if (mutex_ptr -> tx_mutex_inherit == TX_FALSE) + { + + /* Yes, we are done - set the mutex owner to NULL. */ + mutex_ptr -> tx_mutex_owner = TX_NULL; + + /* Restore interrupts. */ + TX_RESTORE + + /* Mutex is now available, return successful status. */ + status = TX_SUCCESS; + } + } + + /* Determine if the processing is complete. */ + if (status == TX_NOT_DONE) + { + + /* Initialize original owner and thread priority. */ + old_owner = TX_NULL; + old_priority = thread_ptr -> tx_thread_user_priority; + + /* Does this mutex support priority inheritance? */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + +#ifndef TX_NOT_INTERRUPTABLE + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Default the inheritance priority to disabled. */ + inheritance_priority = ((UINT) TX_MAX_PRIORITIES); + + /* Search the owned mutexes for this thread to determine the highest priority for this + former mutex owner to return to. */ + next_mutex = thread_ptr -> tx_thread_owned_mutex_list; + while (next_mutex != TX_NULL) + { + + /* Does this mutex support priority inheritance? */ + if (next_mutex -> tx_mutex_inherit == TX_TRUE) + { + + /* Determine if highest priority field of the mutex is higher than the priority to + restore. */ + if (next_mutex -> tx_mutex_highest_priority_waiting < inheritance_priority) + { + + /* Use this priority to return releasing thread to. */ + inheritance_priority = next_mutex -> tx_mutex_highest_priority_waiting; + } + } + + /* Move mutex pointer to the next mutex in the list. */ + next_mutex = next_mutex -> tx_mutex_owned_next; + + /* Are we at the end of the list? */ + if (next_mutex == thread_ptr -> tx_thread_owned_mutex_list) + { + + /* Yes, set the next mutex to NULL. */ + next_mutex = TX_NULL; + } + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts. */ + TX_DISABLE + + /* Undo the temporarily preemption disable. */ + _tx_thread_preempt_disable--; +#endif + + /* Set the inherit priority to that of the highest priority thread waiting on the mutex. */ + thread_ptr -> tx_thread_inherit_priority = inheritance_priority; + + /* Determine if the inheritance priority is less than the default old priority. */ + if (inheritance_priority < old_priority) + { + + /* Yes, update the old priority. */ + old_priority = inheritance_priority; + } + } + + /* Determine if priority inheritance is in effect and there are one or more + threads suspended on the mutex. */ + if (mutex_ptr -> tx_mutex_suspended_count > ((UINT) 1)) + { + + /* Is priority inheritance in effect? */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Yes, this code is simply to ensure the highest priority thread is positioned + at the front of the suspension list. */ + +#ifndef TX_NOT_INTERRUPTABLE + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Call the mutex prioritize processing to ensure the + highest priority thread is resumed. */ +#ifdef TX_MISRA_ENABLE + do + { + status = _tx_mutex_prioritize(mutex_ptr); + } while (status != TX_SUCCESS); +#else + _tx_mutex_prioritize(mutex_ptr); +#endif + + /* At this point, the highest priority thread is at the + front of the suspension list. */ + + /* Optional processing extension. */ + TX_MUTEX_PUT_EXTENSION_1 + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts. */ + TX_DISABLE + + /* Back off the preemption disable. */ + _tx_thread_preempt_disable--; +#endif + } + } + + /* Now determine if there are any threads still waiting on the mutex. */ + if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) + { + + /* No, there are no longer any threads waiting on the mutex. */ + +#ifndef TX_NOT_INTERRUPTABLE + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Mutex is not owned, but it is possible that a thread that + caused a priority inheritance to occur is no longer waiting + on the mutex. */ + + /* Setup the highest priority waiting thread. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES; + + /* Determine if we need to restore priority. */ + if ((mutex_ptr -> tx_mutex_owner) -> tx_thread_priority != old_priority) + { + + /* Yes, restore the priority of thread. */ + _tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, old_priority); + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Back off the preemption disable. */ + _tx_thread_preempt_disable--; +#endif + + /* Set the mutex owner to NULL. */ + mutex_ptr -> tx_mutex_owner = TX_NULL; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Set status to success. */ + status = TX_SUCCESS; + } + else + { + + /* Pickup the thread at the front of the suspension list. */ + thread_ptr = mutex_ptr -> tx_mutex_suspension_list; + + /* Save the previous ownership information, if inheritance is + in effect. */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Remember the old mutex owner. */ + old_owner = mutex_ptr -> tx_mutex_owner; + + /* Setup owner thread priority information. */ + mutex_ptr -> tx_mutex_original_priority = thread_ptr -> tx_thread_priority; + + /* Setup the highest priority waiting thread. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES; + } + + /* Determine how many mutexes are owned by this thread. */ + owned_count = thread_ptr -> tx_thread_owned_mutex_count; + + /* Determine if this thread owns any other mutexes that have priority inheritance. */ + if (owned_count == ((UINT) 0)) + { + + /* The owned mutex list is empty. Add mutex to empty list. */ + thread_ptr -> tx_thread_owned_mutex_list = mutex_ptr; + mutex_ptr -> tx_mutex_owned_next = mutex_ptr; + mutex_ptr -> tx_mutex_owned_previous = mutex_ptr; + } + else + { + + /* Non-empty list. Link up the mutex. */ + + /* Pickup tail pointer. */ + next_mutex = thread_ptr -> tx_thread_owned_mutex_list; + previous_mutex = next_mutex -> tx_mutex_owned_previous; + + /* Place the owned mutex in the list. */ + next_mutex -> tx_mutex_owned_previous = mutex_ptr; + previous_mutex -> tx_mutex_owned_next = mutex_ptr; + + /* Setup this mutex's next and previous created links. */ + mutex_ptr -> tx_mutex_owned_previous = previous_mutex; + mutex_ptr -> tx_mutex_owned_next = next_mutex; + } + + /* Increment the number of mutexes owned counter. */ + thread_ptr -> tx_thread_owned_mutex_count = owned_count + ((UINT) 1); + + /* Mark the Mutex as owned and fill in the corresponding information. */ + mutex_ptr -> tx_mutex_ownership_count = (UINT) 1; + mutex_ptr -> tx_mutex_owner = thread_ptr; + + /* Remove the suspended thread from the list. */ + + /* Decrement the suspension count. */ + mutex_ptr -> tx_mutex_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = mutex_ptr -> tx_mutex_suspended_count; + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + mutex_ptr -> tx_mutex_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + mutex_ptr -> tx_mutex_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Determine if priority inheritance is enabled for this mutex. */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Yes, priority inheritance is requested. */ + + /* Determine if there are any more threads still suspended on the mutex. */ + if (mutex_ptr -> tx_mutex_suspended_count != ((ULONG) 0)) + { + + /* Determine if there are more than one thread suspended on the mutex. */ + if (mutex_ptr -> tx_mutex_suspended_count > ((ULONG) 1)) + { + + /* If so, prioritize the list so the highest priority thread is placed at the + front of the suspension list. */ +#ifdef TX_MISRA_ENABLE + do + { + status = _tx_mutex_prioritize(mutex_ptr); + } while (status != TX_SUCCESS); +#else + _tx_mutex_prioritize(mutex_ptr); +#endif + } + + /* Now, pickup the list head and set the priority. */ + + /* Determine if there still are threads suspended for this mutex. */ + suspended_thread = mutex_ptr -> tx_mutex_suspension_list; + if (suspended_thread != TX_NULL) + { + + /* Setup the highest priority thread waiting on this mutex. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = suspended_thread -> tx_thread_priority; + } + } + + /* Restore previous priority needs to be restored after priority + inheritance. */ + + /* Determine if we need to restore priority. */ + if (old_owner -> tx_thread_priority != old_priority) + { + + /* Restore priority of thread. */ + _tx_mutex_priority_change(old_owner, old_priority); + } + } + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if priority inheritance is enabled for this mutex. */ + if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) + { + + /* Yes, priority inheritance is requested. */ + + /* Determine if there are any more threads still suspended on the mutex. */ + if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS) + { + + /* Prioritize the list so the highest priority thread is placed at the + front of the suspension list. */ +#ifdef TX_MISRA_ENABLE + do + { + status = _tx_mutex_prioritize(mutex_ptr); + } while (status != TX_SUCCESS); +#else + _tx_mutex_prioritize(mutex_ptr); +#endif + + /* Now, pickup the list head and set the priority. */ + + /* Optional processing extension. */ + TX_MUTEX_PUT_EXTENSION_2 + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if there still are threads suspended for this mutex. */ + suspended_thread = mutex_ptr -> tx_mutex_suspension_list; + if (suspended_thread != TX_NULL) + { + + /* Setup the highest priority thread waiting on this mutex. */ + mutex_ptr -> tx_mutex_highest_priority_waiting = suspended_thread -> tx_thread_priority; + } + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Restore previous priority needs to be restored after priority + inheritance. */ + + /* Is the priority different? */ + if (old_owner -> tx_thread_priority != old_priority) + { + + /* Restore the priority of thread. */ + _tx_mutex_priority_change(old_owner, old_priority); + } + } + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Return a successful status. */ + status = TX_SUCCESS; + } + } + } + } + } + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Caller does not own the mutex. */ + status = TX_NOT_OWNED; + } + + /* Return the completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_cleanup.c b/3rd_party/threadx/common/src/tx_queue_cleanup.c new file mode 100644 index 00000000..c6c9f935 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_cleanup.c @@ -0,0 +1,227 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_cleanup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes queue timeout and thread terminate */ +/* actions that require the queue data structures to be cleaned */ +/* up. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to suspended thread's */ +/* control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_timeout Thread timeout processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* _tx_thread_wait_abort Thread wait abort processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) +{ + +#ifndef TX_NOT_INTERRUPTABLE +TX_INTERRUPT_SAVE_AREA +#endif + +TX_QUEUE *queue_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts to remove the suspended thread from the queue. */ + TX_DISABLE + + /* Determine if the cleanup is still required. */ + if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_queue_cleanup)) + { + + /* Check for valid suspension sequence. */ + if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) + { + + /* Setup pointer to queue control block. */ + queue_ptr = TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); + + /* Check for NULL queue pointer. */ + if (queue_ptr != TX_NULL) + { + + /* Is the queue ID valid? */ + if (queue_ptr -> tx_queue_id == TX_QUEUE_ID) + { + + /* Determine if there are any thread suspensions. */ + if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS) + { +#else + + /* Setup pointer to queue control block. */ + queue_ptr = TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); +#endif + + /* Yes, we still have thread suspension! */ + + /* Clear the suspension cleanup flag. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Decrement the suspended count. */ + queue_ptr -> tx_queue_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Remove the suspended thread from the list. */ + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + queue_ptr -> tx_queue_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same suspension list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Determine if we need to update the head pointer. */ + if (queue_ptr -> tx_queue_suspension_list == thread_ptr) + { + + /* Update the list head pointer. */ + queue_ptr -> tx_queue_suspension_list = next_thread; + } + } + + /* Now we need to determine if this cleanup is from a terminate, timeout, + or from a wait abort. */ + if (thread_ptr -> tx_thread_state == TX_QUEUE_SUSP) + { + + /* Timeout condition and the thread still suspended on the queue. + Setup return error status and resume the thread. */ + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the total timeouts counter. */ + _tx_queue_performance_timeout_count++; + + /* Increment the number of timeouts on this queue. */ + queue_ptr -> tx_queue_performance_timeout_count++; +#endif + + /* Setup return status. */ + if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES) + { + + /* Queue full timeout! */ + thread_ptr -> tx_thread_suspend_status = TX_QUEUE_FULL; + } + else + { + + /* Queue empty timeout! */ + thread_ptr -> tx_thread_suspend_status = TX_QUEUE_EMPTY; + } + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread! */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } +#ifndef TX_NOT_INTERRUPTABLE + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_queue_create.c b/3rd_party/threadx/common/src/tx_queue_create.c new file mode 100644 index 00000000..01aec360 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_create.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a message queue. The message size and depth */ +/* of the queue is specified by the caller. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* name_ptr Pointer to queue name */ +/* message_size Size of each queue message */ +/* queue_start Starting address of the queue area*/ +/* queue_size Number of bytes in the queue */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, + VOID *queue_start, ULONG queue_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT capacity; +UINT used_words; +TX_QUEUE *next_queue; +TX_QUEUE *previous_queue; + + + /* Initialize queue control block to all zeros. */ + TX_MEMSET(queue_ptr, 0, (sizeof(TX_QUEUE))); + + /* Setup the basic queue fields. */ + queue_ptr -> tx_queue_name = name_ptr; + + /* Save the message size in the control block. */ + queue_ptr -> tx_queue_message_size = message_size; + + /* Determine how many messages will fit in the queue area and the number + of ULONGs used. */ + capacity = (UINT) (queue_size / ((ULONG) (((ULONG) message_size) * (sizeof(ULONG))))); + used_words = capacity * message_size; + + /* Save the starting address and calculate the ending address of + the queue. Note that the ending address is really one past the + end! */ + queue_ptr -> tx_queue_start = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start); + queue_ptr -> tx_queue_end = TX_ULONG_POINTER_ADD(queue_ptr -> tx_queue_start, used_words); + + /* Set the read and write pointers to the beginning of the queue + area. */ + queue_ptr -> tx_queue_read = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start); + queue_ptr -> tx_queue_write = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start); + + /* Setup the number of enqueued messages and the number of message + slots available in the queue. */ + queue_ptr -> tx_queue_available_storage = (UINT) capacity; + queue_ptr -> tx_queue_capacity = (UINT) capacity; + + /* Disable interrupts to put the queue on the created list. */ + TX_DISABLE + + /* Setup the queue ID to make it valid. */ + queue_ptr -> tx_queue_id = TX_QUEUE_ID; + + /* Place the queue on the list of created queues. First, + check for an empty list. */ + if (_tx_queue_created_count == TX_EMPTY) + { + + /* The created queue list is empty. Add queue to empty list. */ + _tx_queue_created_ptr = queue_ptr; + queue_ptr -> tx_queue_created_next = queue_ptr; + queue_ptr -> tx_queue_created_previous = queue_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_queue = _tx_queue_created_ptr; + previous_queue = next_queue -> tx_queue_created_previous; + + /* Place the new queue in the list. */ + next_queue -> tx_queue_created_previous = queue_ptr; + previous_queue -> tx_queue_created_next = queue_ptr; + + /* Setup this queues's created links. */ + queue_ptr -> tx_queue_created_previous = previous_queue; + queue_ptr -> tx_queue_created_next = next_queue; + } + + /* Increment the created queue count. */ + _tx_queue_created_count++; + + /* Optional queue create extended processing. */ + TX_QUEUE_CREATE_EXTENSION(queue_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, name_ptr, queue_size, message_size) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_CREATE, queue_ptr, message_size, TX_POINTER_TO_ULONG_CONVERT(queue_start), queue_size, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_CREATE_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_delete.c b/3rd_party/threadx/common/src/tx_queue_delete.c new file mode 100644 index 00000000..c0fb13ce --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_delete.c @@ -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 */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified queue. All threads suspended */ +/* on the queue are resumed with the TX_DELETED status code. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_delete(TX_QUEUE *queue_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +UINT suspended_count; +TX_QUEUE *next_queue; +TX_QUEUE *previous_queue; + + + /* Disable interrupts to remove the queue from the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_DELETE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS) + + /* Optional queue delete extended processing. */ + TX_QUEUE_DELETE_EXTENSION(queue_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(queue_ptr) + + /* Log this kernel call. */ + TX_EL_QUEUE_DELETE_INSERT + + /* Clear the queue ID to make it invalid. */ + queue_ptr -> tx_queue_id = TX_CLEAR_ID; + + /* Decrement the number of created queues. */ + _tx_queue_created_count--; + + /* See if the queue is the only one on the list. */ + if (_tx_queue_created_count == TX_EMPTY) + { + + /* Only created queue, just set the created list to NULL. */ + _tx_queue_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_queue = queue_ptr -> tx_queue_created_next; + previous_queue = queue_ptr -> tx_queue_created_previous; + next_queue -> tx_queue_created_previous = previous_queue; + previous_queue -> tx_queue_created_next = next_queue; + + /* See if we have to update the created list head pointer. */ + if (_tx_queue_created_ptr == queue_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_queue_created_ptr = next_queue; + } + } + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Pickup the suspension information. */ + thread_ptr = queue_ptr -> tx_queue_suspension_list; + queue_ptr -> tx_queue_suspension_list = TX_NULL; + suspended_count = queue_ptr -> tx_queue_suspended_count; + queue_ptr -> tx_queue_suspended_count = TX_NO_SUSPENSIONS; + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the queue list to resume any and all threads suspended + on this queue. */ + while (suspended_count != TX_NO_SUSPENSIONS) + { + + /* Decrement the suspension count. */ + suspended_count--; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_DELETED. */ + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + + /* Move the thread pointer ahead. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move to next thread. */ + thread_ptr = next_thread; + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_QUEUE_DELETE_PORT_COMPLETION(queue_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Release previous preempt disable. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_flush.c b/3rd_party/threadx/common/src/tx_queue_flush.c new file mode 100644 index 00000000..ac5c7e36 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_flush.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_flush PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resets the specified queue, if there are any messages */ +/* in it. Messages waiting to be placed on the queue are also thrown */ +/* out. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_flush(TX_QUEUE *queue_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *suspension_list; +UINT suspended_count; +TX_THREAD *thread_ptr; + + + /* Initialize the suspended count and list. */ + suspended_count = TX_NO_SUSPENSIONS; + suspension_list = TX_NULL; + + /* Disable interrupts to reset various queue parameters. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FLUSH, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_FLUSH_INSERT + + /* Determine if there is something on the queue. */ + if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES) + { + + /* Yes, there is something in the queue. */ + + /* Reset the queue parameters to erase all of the queued messages. */ + queue_ptr -> tx_queue_enqueued = TX_NO_MESSAGES; + queue_ptr -> tx_queue_available_storage = queue_ptr -> tx_queue_capacity; + queue_ptr -> tx_queue_read = queue_ptr -> tx_queue_start; + queue_ptr -> tx_queue_write = queue_ptr -> tx_queue_start; + + /* Now determine if there are any threads suspended on a full queue. */ + if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS) + { + + /* Yes, there are threads suspended on this queue, they must be + resumed! */ + + /* Copy the information into temporary variables. */ + suspension_list = queue_ptr -> tx_queue_suspension_list; + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Clear the queue variables. */ + queue_ptr -> tx_queue_suspension_list = TX_NULL; + queue_ptr -> tx_queue_suspended_count = TX_NO_SUSPENSIONS; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + } + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the queue list to resume any and all threads suspended + on this queue. */ + if (suspended_count != TX_NO_SUSPENSIONS) + { + + /* Pickup the thread to resume. */ + thread_ptr = suspension_list; + while (suspended_count != ((ULONG) 0)) + { + + /* Decrement the suspension count. */ + suspended_count--; + + /* Check for a NULL thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Get out of the loop. */ + break; + } + + /* Resume the next suspended thread. */ + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_SUCCESS. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + + /* Move the thread pointer ahead. */ + thread_ptr = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr -> tx_thread_suspended_previous); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr -> tx_thread_suspended_previous); +#endif + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Restore previous preempt posture. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_front_send.c b/3rd_party/threadx/common/src/tx_queue_front_send.c new file mode 100644 index 00000000..51e7b935 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_front_send.c @@ -0,0 +1,423 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_front_send PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places a message at the front of the specified queue. */ +/* If there is no room in the queue, this function returns the */ +/* queue full status. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* source_ptr Pointer to message source */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread routine */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_thread_system_suspend Suspend thread routine */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +ULONG *source; +ULONG *destination; +UINT size; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr); +#endif + + + /* Default the status to TX_SUCCESS. */ + status = TX_SUCCESS; + + /* Disable interrupts to place message in the queue. */ + TX_DISABLE + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the total messages sent counter. */ + _tx_queue_performance_messages_sent_count++; + + /* Increment the number of messages sent to this queue. */ + queue_ptr -> tx_queue_performance_messages_sent_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FRONT_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_FRONT_SEND_INSERT + + /* Pickup the suspended count. */ + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Now check for room in the queue for placing the new message in front. */ + if (queue_ptr -> tx_queue_available_storage != ((UINT) 0)) + { + + /* Yes there is room in the queue. Now determine if there is a thread waiting + for a message. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No thread suspended while waiting for a message from + this queue. */ + + /* Adjust the read pointer since we are adding to the front of the + queue. */ + + /* See if the read pointer is at the beginning of the queue area. */ + if (queue_ptr -> tx_queue_read == queue_ptr -> tx_queue_start) + { + + /* Adjust the read pointer to the last message at the end of the + queue. */ + queue_ptr -> tx_queue_read = TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_end, queue_ptr -> tx_queue_message_size); + } + else + { + + /* Not at the beginning of the queue, just move back one message. */ + queue_ptr -> tx_queue_read = TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_read, queue_ptr -> tx_queue_message_size); + } + + /* Simply place the message in the queue. */ + + /* Reduce the amount of available storage. */ + queue_ptr -> tx_queue_available_storage--; + + /* Increase the enqueued count. */ + queue_ptr -> tx_queue_enqueued++; + + /* Setup source and destination pointers. */ + source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); + destination = queue_ptr -> tx_queue_read; + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this queue. */ + queue_send_notify = queue_ptr -> tx_queue_send_notify; +#endif + + /* Restore interrupts. */ + TX_RESTORE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (queue_send_notify != TX_NULL) + { + + /* Call application queue send notification. */ + (queue_send_notify)(queue_ptr); + } +#endif + } + else + { + + /* Thread suspended waiting for a message. Remove it and copy this message + into its storage area. */ + thread_ptr = queue_ptr -> tx_queue_suspension_list; + + /* See if this is the only suspended thread on the list. */ + suspended_count--; + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + queue_ptr -> tx_queue_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + queue_ptr -> tx_queue_suspension_list = thread_ptr -> tx_thread_suspended_next; + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + queue_ptr -> tx_queue_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Decrement the suspension count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count; + + /* Prepare for resumption of the thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this queue. */ + queue_send_notify = queue_ptr -> tx_queue_send_notify; +#endif + + /* Setup source and destination pointers. */ + source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); + destination = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (queue_send_notify != TX_NULL) + { + + /* Call application queue send notification. */ + (queue_send_notify)(queue_ptr); + } +#endif + } + } + + /* Determine if the caller has requested suspension. */ + else if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_QUEUE_FULL; + } + else + { + + /* Yes, suspension is requested. */ + + /* Prepare for suspension of this thread. */ + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup); + + /* Setup cleanup information, i.e. this queue control + block and the source pointer. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr; + thread_ptr -> tx_thread_additional_suspend_info = (VOID *) source_ptr; + + /* Set the flag to true to indicate a queue front send suspension. */ + thread_ptr -> tx_thread_suspend_option = TX_TRUE; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Place this thread at the front of the suspension list, since it is a + queue front send suspension. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + queue_ptr -> tx_queue_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = queue_ptr -> tx_queue_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + + /* Update the suspension list to put this thread in front, which will put + the message that was removed in the proper relative order when room is + made in the queue. */ + queue_ptr -> tx_queue_suspension_list = thread_ptr; + } + + /* Increment the suspended thread count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1); + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_QUEUE_SUSP; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this queue. */ + queue_send_notify = queue_ptr -> tx_queue_send_notify; +#endif + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS) + { + + /* Check for a notify callback. */ + if (queue_send_notify != TX_NULL) + { + + /* Call application queue send notification. */ + (queue_send_notify)(queue_ptr); + } + } +#endif + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* No room in queue and no suspension requested, return error completion. */ + status = TX_QUEUE_FULL; + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_info_get.c b/3rd_party/threadx/common/src/tx_queue_info_get.c new file mode 100644 index 00000000..3275db72 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_info_get.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified queue. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* name Destination for the queue name */ +/* enqueued Destination for enqueued count */ +/* available_storage Destination for available storage */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on this queue */ +/* suspended_count Destination for suspended count */ +/* next_queue Destination for pointer to next */ +/* queue on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, + TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the queue. */ + if (name != TX_NULL) + { + + *name = queue_ptr -> tx_queue_name; + } + + /* Retrieve the number of messages currently in the queue. */ + if (enqueued != TX_NULL) + { + + *enqueued = (ULONG) queue_ptr -> tx_queue_enqueued; + } + + /* Retrieve the number of messages that will still fit in the queue. */ + if (available_storage != TX_NULL) + { + + *available_storage = (ULONG) queue_ptr -> tx_queue_available_storage; + } + + /* Retrieve the first thread suspended on this queue. */ + if (first_suspended != TX_NULL) + { + + *first_suspended = queue_ptr -> tx_queue_suspension_list; + } + + /* Retrieve the number of threads suspended on this queue. */ + if (suspended_count != TX_NULL) + { + + *suspended_count = (ULONG) queue_ptr -> tx_queue_suspended_count; + } + + /* Retrieve the pointer to the next queue created. */ + if (next_queue != TX_NULL) + { + + *next_queue = queue_ptr -> tx_queue_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_initialize.c b/3rd_party/threadx/common/src/tx_queue_initialize.c new file mode 100644 index 00000000..41fb6fa1 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_initialize.c @@ -0,0 +1,142 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" + + +#ifndef TX_INLINE_INITIALIZATION + +/* Define the head pointer of the created queue list. */ + +TX_QUEUE * _tx_queue_created_ptr; + + +/* Define the variable that holds the number of created queues. */ + +ULONG _tx_queue_created_count; + + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + +/* Define the total number of messages sent. */ + +ULONG _tx_queue_performance_messages_sent_count; + + +/* Define the total number of messages received. */ + +ULONG _tx_queue_performance__messages_received_count; + + +/* Define the total number of queue empty suspensions. */ + +ULONG _tx_queue_performance_empty_suspension_count; + + +/* Define the total number of queue full suspensions. */ + +ULONG _tx_queue_performance_full_suspension_count; + + +/* Define the total number of queue full errors. */ + +ULONG _tx_queue_performance_full_error_count; + + +/* Define the total number of queue timeouts. */ + +ULONG _tx_queue_performance_timeout_count; + +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the queue component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* opt out of function when */ +/* TX_INLINE_INITIALIZATION is */ +/* defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_queue_initialize(VOID) +{ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created queue list and the + number of queues created. */ + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = TX_EMPTY; + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Initialize the queue performance counters. */ + _tx_queue_performance_messages_sent_count = ((ULONG) 0); + _tx_queue_performance__messages_received_count = ((ULONG) 0); + _tx_queue_performance_empty_suspension_count = ((ULONG) 0); + _tx_queue_performance_full_suspension_count = ((ULONG) 0); + _tx_queue_performance_timeout_count = ((ULONG) 0); +#endif +#endif +} +#endif diff --git a/3rd_party/threadx/common/src/tx_queue_performance_info_get.c b/3rd_party/threadx/common/src/tx_queue_performance_info_get.c new file mode 100644 index 00000000..4bdb62e6 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_performance_info_get.c @@ -0,0 +1,231 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* queue. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* messages_sent Destination for messages sent */ +/* messages_received Destination for messages received */ +/* empty_suspensions Destination for number of empty */ +/* queue suspensions */ +/* full_suspensions Destination for number of full */ +/* queue suspensions */ +/* full_errors Destination for queue full errors */ +/* returned - no suspension */ +/* timeouts Destination for number of timeouts*/ +/* on this queue */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received, + ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts) +{ + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Determine if this is a legal request. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the queue ID is invalid. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PERFORMANCE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the number of messages sent to this queue. */ + if (messages_sent != TX_NULL) + { + + *messages_sent = queue_ptr -> tx_queue_performance_messages_sent_count; + } + + /* Retrieve the number of messages received from this queue. */ + if (messages_received != TX_NULL) + { + + *messages_received = queue_ptr -> tx_queue_performance_messages_received_count; + } + + /* Retrieve the number of empty queue suspensions on this queue. */ + if (empty_suspensions != TX_NULL) + { + + *empty_suspensions = queue_ptr -> tx_queue_performance_empty_suspension_count; + } + + /* Retrieve the number of full queue suspensions on this queue. */ + if (full_suspensions != TX_NULL) + { + + *full_suspensions = queue_ptr -> tx_queue_performance_full_suspension_count; + } + + /* Retrieve the number of full errors (no suspension!) on this queue. */ + if (full_errors != TX_NULL) + { + + *full_errors = queue_ptr -> tx_queue_performance_full_error_count; + } + + /* Retrieve the number of timeouts on this queue. */ + if (timeouts != TX_NULL) + { + + *timeouts = queue_ptr -> tx_queue_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + status = TX_SUCCESS; + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (queue_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (messages_sent != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (messages_received != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (empty_suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (full_suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (full_errors != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_queue_performance_system_info_get.c new file mode 100644 index 00000000..0299d068 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_performance_system_info_get.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves queue system performance information. */ +/* */ +/* INPUT */ +/* */ +/* messages_sent Destination for total messages */ +/* sent */ +/* messages_received Destination for total messages */ +/* received */ +/* empty_suspensions Destination for total empty */ +/* queue suspensions */ +/* full_suspensions Destination for total full */ +/* queue suspensions */ +/* full_errors Destination for total queue full */ +/* errors returned - no suspension */ +/* timeouts Destination for total number of */ +/* timeouts */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_performance_system_info_get(ULONG *messages_sent, ULONG *messages_received, + ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts) +{ + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the total number of queue messages sent. */ + if (messages_sent != TX_NULL) + { + + *messages_sent = _tx_queue_performance_messages_sent_count; + } + + /* Retrieve the total number of queue messages received. */ + if (messages_received != TX_NULL) + { + + *messages_received = _tx_queue_performance__messages_received_count; + } + + /* Retrieve the total number of empty queue suspensions. */ + if (empty_suspensions != TX_NULL) + { + + *empty_suspensions = _tx_queue_performance_empty_suspension_count; + } + + /* Retrieve the total number of full queue suspensions. */ + if (full_suspensions != TX_NULL) + { + + *full_suspensions = _tx_queue_performance_full_suspension_count; + } + + /* Retrieve the total number of full errors. */ + if (full_errors != TX_NULL) + { + + *full_errors = _tx_queue_performance_full_error_count; + } + + /* Retrieve the total number of queue timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_queue_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (messages_sent != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (messages_received != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (empty_suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (full_suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (full_errors != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_queue_prioritize.c b/3rd_party/threadx/common/src/tx_queue_prioritize.c new file mode 100644 index 00000000..ae80ce79 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_prioritize.c @@ -0,0 +1,251 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the highest priority suspended thread at the */ +/* front of the suspension list. All other threads remain in the same */ +/* FIFO suspension order. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_prioritize(TX_QUEUE *queue_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *priority_thread_ptr; +TX_THREAD *head_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT list_changed; + + + /* Disable interrupts to place message in the queue. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PRIORITIZE, queue_ptr, queue_ptr -> tx_queue_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_PRIORITIZE_INSERT + + /* Pickup the suspended count. */ + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Determine if there are fewer than 2 suspended threads. */ + if (suspended_count < ((UINT) 2)) + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Determine if there how many threads are suspended on this queue. */ + else if (suspended_count == ((UINT) 2)) + { + + /* Pickup the head pointer and the next pointer. */ + head_ptr = queue_ptr -> tx_queue_suspension_list; + next_thread = head_ptr -> tx_thread_suspended_next; + + /* Determine if the next suspended thread has a higher priority. */ + if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) + { + + /* Yes, move the list head to the next thread. */ + queue_ptr -> tx_queue_suspension_list = next_thread; + } + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = queue_ptr -> tx_queue_suspension_list; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Set the list changed flag to false. */ + list_changed = TX_FALSE; + + /* Search through the list to find the highest priority thread. */ + do + { + + /* Is the current thread higher priority? */ + if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) + { + + /* Yes, remember that this thread is the highest priority. */ + priority_thread_ptr = thread_ptr; + } + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Determine if any changes to the list have occurred while + interrupts were enabled. */ + + /* Is the list head the same? */ + if (head_ptr != queue_ptr -> tx_queue_suspension_list) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + else + { + + /* Is the suspended count the same? */ + if (suspended_count != queue_ptr -> tx_queue_suspended_count) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + } + + /* Determine if the list has changed. */ + if (list_changed == TX_FALSE) + { + + /* Move the thread pointer to the next thread. */ + thread_ptr = thread_ptr -> tx_thread_suspended_next; + } + else + { + + /* Save the suspension count and head pointer. */ + head_ptr = queue_ptr -> tx_queue_suspension_list; + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Reset the list changed flag. */ + list_changed = TX_FALSE; + } + + } while (thread_ptr != head_ptr); + + /* Release preemption. */ + _tx_thread_preempt_disable--; + + /* Now determine if the highest priority thread is at the front + of the list. */ + if (priority_thread_ptr != head_ptr) + { + + /* No, we need to move the highest priority suspended thread to the + front of the list. */ + + /* First, remove the highest priority thread by updating the + adjacent suspended threads. */ + next_thread = priority_thread_ptr -> tx_thread_suspended_next; + previous_thread = priority_thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Now, link the highest priority thread at the front of the list. */ + previous_thread = head_ptr -> tx_thread_suspended_previous; + priority_thread_ptr -> tx_thread_suspended_next = head_ptr; + priority_thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = priority_thread_ptr; + head_ptr -> tx_thread_suspended_previous = priority_thread_ptr; + + /* Move the list head pointer to the highest priority suspended thread. */ + queue_ptr -> tx_queue_suspension_list = priority_thread_ptr; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + + /* Return successful status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_receive.c b/3rd_party/threadx/common/src/tx_queue_receive.c new file mode 100644 index 00000000..40568812 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_receive.c @@ -0,0 +1,488 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_receive PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a message from the specified queue. If there */ +/* are no messages in the queue, this function waits according to the */ +/* option specified. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* destination_ptr Pointer to message destination */ +/* **** MUST BE LARGE ENOUGH TO */ +/* HOLD MESSAGE **** */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread routine */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_thread_system_suspend Suspend thread routine */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +ULONG *source; +ULONG *destination; +UINT size; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; + + + /* Default the status to TX_SUCCESS. */ + status = TX_SUCCESS; + + /* Disable interrupts to receive message from queue. */ + TX_DISABLE + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the total messages received counter. */ + _tx_queue_performance__messages_received_count++; + + /* Increment the number of messages received from this queue. */ + queue_ptr -> tx_queue_performance_messages_received_count++; + +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_RECEIVE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(destination_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_RECEIVE_INSERT + + /* Pickup the thread suspension count. */ + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Determine if there is anything in the queue. */ + if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES) + { + + /* Determine if there are any suspensions. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* There is a message waiting in the queue and there are no suspensi. */ + + /* Setup source and destination pointers. */ + source = queue_ptr -> tx_queue_read; + destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr); + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Determine if we are at the end. */ + if (source == queue_ptr -> tx_queue_end) + { + + /* Yes, wrap around to the beginning. */ + source = queue_ptr -> tx_queue_start; + } + + /* Setup the queue read pointer. */ + queue_ptr -> tx_queue_read = source; + + /* Increase the amount of available storage. */ + queue_ptr -> tx_queue_available_storage++; + + /* Decrease the enqueued count. */ + queue_ptr -> tx_queue_enqueued--; + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* At this point we know the queue is full. */ + + /* Pickup thread suspension list head pointer. */ + thread_ptr = queue_ptr -> tx_queue_suspension_list; + + /* Now determine if there is a queue front suspension active. */ + + /* Is the front suspension flag set? */ + if (thread_ptr -> tx_thread_suspend_option == TX_TRUE) + { + + /* Yes, a queue front suspension is present. */ + + /* Return the message associated with this suspension. */ + + /* Setup source and destination pointers. */ + source = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr); + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Message is now in the caller's destination. See if this is the only suspended thread + on the list. */ + suspended_count--; + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + queue_ptr -> tx_queue_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + queue_ptr -> tx_queue_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Decrement the suspension count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count; + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + } + else + { + + /* At this point, we know that the queue is full and there + are one or more threads suspended trying to send another + message to this queue. */ + + /* Setup source and destination pointers. */ + source = queue_ptr -> tx_queue_read; + destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr); + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Determine if we are at the end. */ + if (source == queue_ptr -> tx_queue_end) + { + + /* Yes, wrap around to the beginning. */ + source = queue_ptr -> tx_queue_start; + } + + /* Setup the queue read pointer. */ + queue_ptr -> tx_queue_read = source; + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE + + /* Interrupts are enabled briefly here to keep the interrupt + lockout time deterministic. */ + + /* Disable interrupts again. */ + TX_DISABLE +#endif + + /* Decrement the preemption disable variable. */ + _tx_thread_preempt_disable--; + + /* Setup source and destination pointers. */ + source = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + destination = queue_ptr -> tx_queue_write; + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Determine if we are at the end. */ + if (destination == queue_ptr -> tx_queue_end) + { + + /* Yes, wrap around to the beginning. */ + destination = queue_ptr -> tx_queue_start; + } + + /* Adjust the write pointer. */ + queue_ptr -> tx_queue_write = destination; + + /* Pickup thread pointer. */ + thread_ptr = queue_ptr -> tx_queue_suspension_list; + + /* Message is now in the queue. See if this is the only suspended thread + on the list. */ + suspended_count--; + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + queue_ptr -> tx_queue_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + queue_ptr -> tx_queue_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Decrement the suspension count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count; + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + } + } + } + + /* Determine if the request specifies suspension. */ + else if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_QUEUE_EMPTY; + } + else + { + + /* Prepare for suspension of this thread. */ + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the total queue empty suspensions counter. */ + _tx_queue_performance_empty_suspension_count++; + + /* Increment the number of empty suspensions on this queue. */ + queue_ptr -> tx_queue_performance_empty_suspension_count++; +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup); + + /* Setup cleanup information, i.e. this queue control + block and the source pointer. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr; + thread_ptr -> tx_thread_additional_suspend_info = (VOID *) destination_ptr; + thread_ptr -> tx_thread_suspend_option = TX_FALSE; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Setup suspension list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + queue_ptr -> tx_queue_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = queue_ptr -> tx_queue_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Increment the suspended thread count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1); + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_QUEUE_SUSP; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Immediate return, return error completion. */ + status = TX_QUEUE_EMPTY; + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_send.c b/3rd_party/threadx/common/src/tx_queue_send.c new file mode 100644 index 00000000..7cbb9b73 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_send.c @@ -0,0 +1,428 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_send PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places a message into the specified queue. If there */ +/* is no room in the queue, this function waits according to the */ +/* option specified. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* source_ptr Pointer to message source */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread routine */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_thread_system_suspend Suspend thread routine */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +ULONG *source; +ULONG *destination; +UINT size; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr); +#endif + + + /* Default the status to TX_SUCCESS. */ + status = TX_SUCCESS; + + /* Disable interrupts to place message in the queue. */ + TX_DISABLE + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the total messages sent counter. */ + _tx_queue_performance_messages_sent_count++; + + /* Increment the number of messages sent to this queue. */ + queue_ptr -> tx_queue_performance_messages_sent_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS) + + /* Log this kernel call. */ + TX_EL_QUEUE_SEND_INSERT + + /* Pickup the thread suspension count. */ + suspended_count = queue_ptr -> tx_queue_suspended_count; + + /* Determine if there is room in the queue. */ + if (queue_ptr -> tx_queue_available_storage != TX_NO_MESSAGES) + { + + /* There is room for the message in the queue. */ + + /* Determine if there are suspended on this queue. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No suspended threads, simply place the message in the queue. */ + + /* Reduce the amount of available storage. */ + queue_ptr -> tx_queue_available_storage--; + + /* Increase the enqueued count. */ + queue_ptr -> tx_queue_enqueued++; + + /* Setup source and destination pointers. */ + source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); + destination = queue_ptr -> tx_queue_write; + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Determine if we are at the end. */ + if (destination == queue_ptr -> tx_queue_end) + { + + /* Yes, wrap around to the beginning. */ + destination = queue_ptr -> tx_queue_start; + } + + /* Adjust the write pointer. */ + queue_ptr -> tx_queue_write = destination; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this queue. */ + queue_send_notify = queue_ptr -> tx_queue_send_notify; +#endif + + /* No thread suspended, just return to caller. */ + + /* Restore interrupts. */ + TX_RESTORE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (queue_send_notify != TX_NULL) + { + + /* Call application queue send notification. */ + (queue_send_notify)(queue_ptr); + } +#endif + } + else + { + + /* There is a thread suspended on an empty queue. Simply + copy the message to the suspended thread's destination + pointer. */ + + /* Pickup the head of the suspension list. */ + thread_ptr = queue_ptr -> tx_queue_suspension_list; + + /* See if this is the only suspended thread on the list. */ + suspended_count--; + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + queue_ptr -> tx_queue_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + queue_ptr -> tx_queue_suspension_list = thread_ptr -> tx_thread_suspended_next; + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + queue_ptr -> tx_queue_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Decrement the suspension count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count; + + /* Prepare for resumption of the thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Setup source and destination pointers. */ + source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr); + destination = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info); + size = queue_ptr -> tx_queue_message_size; + + /* Copy message. Note that the source and destination pointers are + incremented by the macro. */ + TX_QUEUE_MESSAGE_COPY(source, destination, size) + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this queue. */ + queue_send_notify = queue_ptr -> tx_queue_send_notify; +#endif + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (queue_send_notify != TX_NULL) + { + + /* Call application queue send notification. */ + (queue_send_notify)(queue_ptr); + } +#endif + } + } + + /* At this point, the queue is full. Determine if suspension is requested. */ + else if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_QUEUE_FULL; + } + else + { + + /* Yes, prepare for suspension of this thread. */ + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of queue full suspensions. */ + _tx_queue_performance_full_suspension_count++; + + /* Increment the number of full suspensions on this queue. */ + queue_ptr -> tx_queue_performance_full_suspension_count++; +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup); + + /* Setup cleanup information, i.e. this queue control + block and the source pointer. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr; + thread_ptr -> tx_thread_additional_suspend_info = (VOID *) source_ptr; + thread_ptr -> tx_thread_suspend_option = TX_FALSE; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Setup suspension list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + queue_ptr -> tx_queue_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = queue_ptr -> tx_queue_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Increment the suspended thread count. */ + queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1); + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_QUEUE_SUSP; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the notify callback routine for this queue. */ + queue_send_notify = queue_ptr -> tx_queue_send_notify; +#endif + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if a notify callback is required. */ + if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS) + { + + /* Determine if there is a notify callback. */ + if (queue_send_notify != TX_NULL) + { + + /* Call application queue send notification. */ + (queue_send_notify)(queue_ptr); + } + } +#endif + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Otherwise, just return a queue full error message to the caller. */ + +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + + /* Increment the number of full non-suspensions on this queue. */ + queue_ptr -> tx_queue_performance_full_error_count++; + + /* Increment the total number of full non-suspensions. */ + _tx_queue_performance_full_error_count++; +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Return error completion. */ + status = TX_QUEUE_FULL; + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_queue_send_notify.c b/3rd_party/threadx/common/src/tx_queue_send_notify.c new file mode 100644 index 00000000..a0bbf527 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_queue_send_notify.c @@ -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 */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_queue_send_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers an application callback function that is */ +/* called whenever a messages is sent to this queue. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block*/ +/* queue_send_notify Application callback function */ +/* (TX_NULL disables notify) */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)) +{ + +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + + TX_QUEUE_NOT_USED(queue_ptr); + TX_QUEUE_SEND_NOTIFY_NOT_USED(queue_send_notify); + + /* Feature is not enabled, return error. */ + return(TX_FEATURE_NOT_ENABLED); +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Make entry in event log. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND_NOTIFY, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS) + + /* Make entry in event log. */ + TX_EL_QUEUE_SEND_NOTIFY_INSERT + + /* Setup queue send notification callback function. */ + queue_ptr -> tx_queue_send_notify = queue_send_notify; + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success to caller. */ + return(TX_SUCCESS); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_ceiling_put.c b/3rd_party/threadx/common/src/tx_semaphore_ceiling_put.c new file mode 100644 index 00000000..30668683 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_ceiling_put.c @@ -0,0 +1,245 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_ceiling_put PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function puts an instance into the specified counting */ +/* semaphore up to the specified semaphore ceiling. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore */ +/* ceiling Maximum value of semaphore */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume */ +/* thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling) +{ + +TX_INTERRUPT_SAVE_AREA + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr); +#endif + +TX_THREAD *thread_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; + + + /* Default the status to TX_SUCCESS. */ + status = TX_SUCCESS; + + /* Disable interrupts to put an instance back to the semaphore. */ + TX_DISABLE + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Increment the total semaphore put counter. */ + _tx_semaphore_performance_put_count++; + + /* Increment the number of puts on this semaphore. */ + semaphore_ptr -> tx_semaphore_performance_put_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, ceiling, TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_CEILING_PUT_INSERT + + /* Pickup the number of suspended threads. */ + suspended_count = semaphore_ptr -> tx_semaphore_suspended_count; + + /* Determine if there are any threads suspended on the semaphore. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Determine if the ceiling has been exceeded. */ + if (semaphore_ptr -> tx_semaphore_count >= ceiling) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Return an error. */ + status = TX_CEILING_EXCEEDED; + } + else + { + + /* Increment the semaphore count. */ + semaphore_ptr -> tx_semaphore_count++; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the application notify function. */ + semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify; +#endif + + /* Restore interrupts. */ + TX_RESTORE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if notification is required. */ + if (semaphore_put_notify != TX_NULL) + { + + /* Yes, call the appropriate notify callback function. */ + (semaphore_put_notify)(semaphore_ptr); + } +#endif + + /* Return successful completion status. */ + status = TX_SUCCESS; + } + } + else + { + + /* Remove the suspended thread from the list. */ + + /* Pickup the pointer to the first suspended thread. */ + thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list; + + /* See if this is the only suspended thread on the list. */ + suspended_count--; + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + semaphore_ptr -> tx_semaphore_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Decrement the suspension count. */ + semaphore_ptr -> tx_semaphore_suspended_count = suspended_count; + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the application notify function. */ + semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify; +#endif + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if notification is required. */ + if (semaphore_put_notify != TX_NULL) + { + + /* Yes, call the appropriate notify callback function. */ + (semaphore_put_notify)(semaphore_ptr); + } +#endif + } + + /* Return successful completion. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_cleanup.c b/3rd_party/threadx/common/src/tx_semaphore_cleanup.c new file mode 100644 index 00000000..bb0f98f5 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_cleanup.c @@ -0,0 +1,217 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_cleanup PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes semaphore timeout and thread terminate */ +/* actions that require the semaphore data structures to be cleaned */ +/* up. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to suspended thread's */ +/* control block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_timeout Thread timeout processing */ +/* _tx_thread_terminate Thread terminate processing */ +/* _tx_thread_wait_abort Thread wait abort processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence) +{ + +#ifndef TX_NOT_INTERRUPTABLE +TX_INTERRUPT_SAVE_AREA +#endif + +TX_SEMAPHORE *semaphore_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts to remove the suspended thread from the semaphore. */ + TX_DISABLE + + /* Determine if the cleanup is still required. */ + if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_semaphore_cleanup)) + { + + /* Check for valid suspension sequence. */ + if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence) + { + + /* Setup pointer to semaphore control block. */ + semaphore_ptr = TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); + + /* Check for a NULL semaphore pointer. */ + if (semaphore_ptr != TX_NULL) + { + + /* Check for a valid semaphore ID. */ + if (semaphore_ptr -> tx_semaphore_id == TX_SEMAPHORE_ID) + { + + /* Determine if there are any thread suspensions. */ + if (semaphore_ptr -> tx_semaphore_suspended_count != TX_NO_SUSPENSIONS) + { +#else + + /* Setup pointer to semaphore control block. */ + semaphore_ptr = TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block); +#endif + + /* Yes, we still have thread suspension! */ + + /* Clear the suspension cleanup flag. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Decrement the suspended count. */ + semaphore_ptr -> tx_semaphore_suspended_count--; + + /* Pickup the suspended count. */ + suspended_count = semaphore_ptr -> tx_semaphore_suspended_count; + + /* Remove the suspended thread from the list. */ + + /* See if this is the only suspended thread on the list. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same suspension list. */ + + /* Update the links of the adjacent threads. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Determine if we need to update the head pointer. */ + if (semaphore_ptr -> tx_semaphore_suspension_list == thread_ptr) + { + + /* Update the list head pointer. */ + semaphore_ptr -> tx_semaphore_suspension_list = next_thread; + } + } + + /* Now we need to determine if this cleanup is from a terminate, timeout, + or from a wait abort. */ + if (thread_ptr -> tx_thread_state == TX_SEMAPHORE_SUSP) + { + + /* Timeout condition and the thread is still suspended on the semaphore. + Setup return error status and resume the thread. */ + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Increment the total timeouts counter. */ + _tx_semaphore_performance_timeout_count++; + + /* Increment the number of timeouts on this semaphore. */ + semaphore_ptr -> tx_semaphore_performance_timeout_count++; +#endif + + /* Setup return status. */ + thread_ptr -> tx_thread_suspend_status = TX_NO_INSTANCE; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread! */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } +#ifndef TX_NOT_INTERRUPTABLE + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_create.c b/3rd_party/threadx/common/src/tx_semaphore_create.c new file mode 100644 index 00000000..31527d3a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_create.c @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a counting semaphore with the initial count */ +/* specified in this call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* name_ptr Pointer to semaphore name */ +/* initial_count Initial semaphore count */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_SEMAPHORE *next_semaphore; +TX_SEMAPHORE *previous_semaphore; + + + /* Initialize semaphore control block to all zeros. */ + TX_MEMSET(semaphore_ptr, 0, (sizeof(TX_SEMAPHORE))); + + /* Setup the basic semaphore fields. */ + semaphore_ptr -> tx_semaphore_name = name_ptr; + semaphore_ptr -> tx_semaphore_count = initial_count; + + /* Disable interrupts to place the semaphore on the created list. */ + TX_DISABLE + + /* Setup the semaphore ID to make it valid. */ + semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID; + + /* Place the semaphore on the list of created semaphores. First, + check for an empty list. */ + if (_tx_semaphore_created_count == TX_EMPTY) + { + + /* The created semaphore list is empty. Add semaphore to empty list. */ + _tx_semaphore_created_ptr = semaphore_ptr; + semaphore_ptr -> tx_semaphore_created_next = semaphore_ptr; + semaphore_ptr -> tx_semaphore_created_previous = semaphore_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_semaphore = _tx_semaphore_created_ptr; + previous_semaphore = next_semaphore -> tx_semaphore_created_previous; + + /* Place the new semaphore in the list. */ + next_semaphore -> tx_semaphore_created_previous = semaphore_ptr; + previous_semaphore -> tx_semaphore_created_next = semaphore_ptr; + + /* Setup this semaphore's next and previous created links. */ + semaphore_ptr -> tx_semaphore_created_previous = previous_semaphore; + semaphore_ptr -> tx_semaphore_created_next = next_semaphore; + } + + /* Increment the created count. */ + _tx_semaphore_created_count++; + + /* Optional semaphore create extended processing. */ + TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, name_ptr, initial_count, 0) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CREATE, semaphore_ptr, initial_count, TX_POINTER_TO_ULONG_CONVERT(&next_semaphore), 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_CREATE_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_delete.c b/3rd_party/threadx/common/src/tx_semaphore_delete.c new file mode 100644 index 00000000..0a735474 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_delete.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified semaphore. All threads */ +/* suspended on the semaphore are resumed with the TX_DELETED status */ +/* code. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +UINT suspended_count; +TX_SEMAPHORE *next_semaphore; +TX_SEMAPHORE *previous_semaphore; + + + /* Disable interrupts to remove the semaphore from the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_DELETE, semaphore_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Optional semaphore delete extended processing. */ + TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(semaphore_ptr) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_DELETE_INSERT + + /* Clear the semaphore ID to make it invalid. */ + semaphore_ptr -> tx_semaphore_id = TX_CLEAR_ID; + + /* Decrement the number of semaphores. */ + _tx_semaphore_created_count--; + + /* See if the semaphore is the only one on the list. */ + if (_tx_semaphore_created_count == TX_EMPTY) + { + + /* Only created semaphore, just set the created list to NULL. */ + _tx_semaphore_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_semaphore = semaphore_ptr -> tx_semaphore_created_next; + previous_semaphore = semaphore_ptr -> tx_semaphore_created_previous; + next_semaphore -> tx_semaphore_created_previous = previous_semaphore; + previous_semaphore -> tx_semaphore_created_next = next_semaphore; + + /* See if we have to update the created list head pointer. */ + if (_tx_semaphore_created_ptr == semaphore_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_semaphore_created_ptr = next_semaphore; + } + } + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Pickup the suspension information. */ + thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list; + semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL; + suspended_count = semaphore_ptr -> tx_semaphore_suspended_count; + semaphore_ptr -> tx_semaphore_suspended_count = TX_NO_SUSPENSIONS; + + /* Restore interrupts. */ + TX_RESTORE + + /* Walk through the semaphore list to resume any and all threads suspended + on this semaphore. */ + while (suspended_count != TX_NO_SUSPENSIONS) + { + + /* Decrement the suspension count. */ + suspended_count--; + + /* Lockout interrupts. */ + TX_DISABLE + + /* Clear the cleanup pointer, this prevents the timeout from doing + anything. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + + /* Set the return status in the thread to TX_DELETED. */ + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + + /* Move the thread pointer ahead. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption again. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Move to next thread. */ + thread_ptr = next_thread; + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_SEMAPHORE_DELETE_PORT_COMPLETION(semaphore_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Release previous preempt disable. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_get.c b/3rd_party/threadx/common/src/tx_semaphore_get.c new file mode 100644 index 00000000..7a0a6e13 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_get.c @@ -0,0 +1,234 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets an instance from the specified counting */ +/* semaphore. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Suspend thread service */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; + + + /* Default the status to TX_SUCCESS. */ + status = TX_SUCCESS; + + /* Disable interrupts to get an instance from the semaphore. */ + TX_DISABLE + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Increment the total semaphore get counter. */ + _tx_semaphore_performance_get_count++; + + /* Increment the number of attempts to get this semaphore. */ + semaphore_ptr -> tx_semaphore_performance_get_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_GET, semaphore_ptr, wait_option, semaphore_ptr -> tx_semaphore_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_GET_INSERT + + /* Determine if there is an instance of the semaphore. */ + if (semaphore_ptr -> tx_semaphore_count != ((ULONG) 0)) + { + + /* Decrement the semaphore count. */ + semaphore_ptr -> tx_semaphore_count--; + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Determine if the request specifies suspension. */ + else if (wait_option != TX_NO_WAIT) + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_NO_INSTANCE; + } + else + { + + /* Prepare for suspension of this thread. */ + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Increment the total semaphore suspensions counter. */ + _tx_semaphore_performance_suspension_count++; + + /* Increment the number of suspensions on this semaphore. */ + semaphore_ptr -> tx_semaphore_performance_suspension_count++; +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Setup cleanup routine pointer. */ + thread_ptr -> tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup); + + /* Setup cleanup information, i.e. this semaphore control + block. */ + thread_ptr -> tx_thread_suspend_control_block = (VOID *) semaphore_ptr; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the suspension sequence number, which is used to identify + this suspension event. */ + thread_ptr -> tx_thread_suspension_sequence++; +#endif + + /* Setup suspension list. */ + if (semaphore_ptr -> tx_semaphore_suspended_count == TX_NO_SUSPENSIONS) + { + + /* No other threads are suspended. Setup the head pointer and + just setup this threads pointers to itself. */ + semaphore_ptr -> tx_semaphore_suspension_list = thread_ptr; + thread_ptr -> tx_thread_suspended_next = thread_ptr; + thread_ptr -> tx_thread_suspended_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add current thread to the end. */ + next_thread = semaphore_ptr -> tx_semaphore_suspension_list; + thread_ptr -> tx_thread_suspended_next = next_thread; + previous_thread = next_thread -> tx_thread_suspended_previous; + thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = thread_ptr; + next_thread -> tx_thread_suspended_previous = thread_ptr; + } + + /* Increment the number of suspensions. */ + semaphore_ptr -> tx_semaphore_suspended_count++; + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_SEMAPHORE_SUSP; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + + /* Return the completion status. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Immediate return, return error completion. */ + status = TX_NO_INSTANCE; + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_info_get.c b/3rd_party/threadx/common/src/tx_semaphore_info_get.c new file mode 100644 index 00000000..e79ae662 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_info_get.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified semaphore. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* name Destination for the semaphore name*/ +/* current_value Destination for current value of */ +/* the semaphore */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on semaphore */ +/* suspended_count Destination for suspended count */ +/* next_semaphore Destination for pointer to next */ +/* semaphore on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, + TX_THREAD **first_suspended, ULONG *suspended_count, + TX_SEMAPHORE **next_semaphore) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the semaphore. */ + if (name != TX_NULL) + { + + *name = semaphore_ptr -> tx_semaphore_name; + } + + /* Retrieve the current value of the semaphore. */ + if (current_value != TX_NULL) + { + + *current_value = semaphore_ptr -> tx_semaphore_count; + } + + /* Retrieve the first thread suspended on this semaphore. */ + if (first_suspended != TX_NULL) + { + + *first_suspended = semaphore_ptr -> tx_semaphore_suspension_list; + } + + /* Retrieve the number of threads suspended on this semaphore. */ + if (suspended_count != TX_NULL) + { + + *suspended_count = (ULONG) semaphore_ptr -> tx_semaphore_suspended_count; + } + + /* Retrieve the pointer to the next semaphore created. */ + if (next_semaphore != TX_NULL) + { + + *next_semaphore = semaphore_ptr -> tx_semaphore_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_initialize.c b/3rd_party/threadx/common/src/tx_semaphore_initialize.c new file mode 100644 index 00000000..a304e54b --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_initialize.c @@ -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 */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" + + +#ifndef TX_INLINE_INITIALIZATION + +/* Locate semaphore component data in this file. */ + +/* Define the head pointer of the created semaphore list. */ + +TX_SEMAPHORE * _tx_semaphore_created_ptr; + + +/* Define the variable that holds the number of created semaphores. */ + +ULONG _tx_semaphore_created_count; + + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + +/* Define the total number of semaphore puts. */ + +ULONG _tx_semaphore_performance_put_count; + + +/* Define the total number of semaphore gets. */ + +ULONG _tx_semaphore_performance_get_count; + + +/* Define the total number of semaphore suspensions. */ + +ULONG _tx_semaphore_performance_suspension_count; + + +/* Define the total number of semaphore timeouts. */ + +ULONG _tx_semaphore_performance_timeout_count; + +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the semaphore component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* opt out of function when */ +/* TX_INLINE_INITIALIZATION is */ +/* defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_semaphore_initialize(VOID) +{ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created semaphores list and the + number of semaphores created. */ + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = TX_EMPTY; + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Initialize semaphore performance counters. */ + _tx_semaphore_performance_put_count = ((ULONG) 0); + _tx_semaphore_performance_get_count = ((ULONG) 0); + _tx_semaphore_performance_suspension_count = ((ULONG) 0); + _tx_semaphore_performance_timeout_count = ((ULONG) 0); +#endif +#endif +} +#endif diff --git a/3rd_party/threadx/common/src/tx_semaphore_performance_info_get.c b/3rd_party/threadx/common/src/tx_semaphore_performance_info_get.c new file mode 100644 index 00000000..29e2b5a3 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_performance_info_get.c @@ -0,0 +1,203 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* semaphore. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* puts Destination for the number of */ +/* puts on to this semaphore */ +/* gets Destination for the number of */ +/* gets on this semaphore */ +/* suspensions Destination for the number of */ +/* suspensions on this semaphore */ +/* timeouts Destination for number of timeouts*/ +/* on this semaphore */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets, + ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Determine if this is a legal request. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the semaphore ID is invalid. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PERFORMANCE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the number of puts on this semaphore. */ + if (puts != TX_NULL) + { + + *puts = semaphore_ptr -> tx_semaphore_performance_put_count; + } + + /* Retrieve the number of gets on this semaphore. */ + if (gets != TX_NULL) + { + + *gets = semaphore_ptr -> tx_semaphore_performance_get_count; + } + + /* Retrieve the number of suspensions on this semaphore. */ + if (suspensions != TX_NULL) + { + + *suspensions = semaphore_ptr -> tx_semaphore_performance_suspension_count; + } + + /* Retrieve the number of timeouts on this semaphore. */ + if (timeouts != TX_NULL) + { + + *timeouts = semaphore_ptr -> tx_semaphore_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return successful completion. */ + status = TX_SUCCESS; + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (semaphore_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (puts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (gets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_semaphore_performance_system_info_get.c new file mode 100644 index 00000000..fb63710d --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_performance_system_info_get.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves system semaphore performance information. */ +/* */ +/* INPUT */ +/* */ +/* puts Destination for total number of */ +/* semaphore puts */ +/* gets Destination for total number of */ +/* semaphore gets */ +/* suspensions Destination for total number of */ +/* semaphore suspensions */ +/* timeouts Destination for total number of */ +/* timeouts */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions, ULONG *timeouts) +{ + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the total number of semaphore puts. */ + if (puts != TX_NULL) + { + + *puts = _tx_semaphore_performance_put_count; + } + + /* Retrieve the total number of semaphore gets. */ + if (gets != TX_NULL) + { + + *gets = _tx_semaphore_performance_get_count; + } + + /* Retrieve the total number of semaphore suspensions. */ + if (suspensions != TX_NULL) + { + + *suspensions = _tx_semaphore_performance_suspension_count; + } + + /* Retrieve the total number of semaphore timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_semaphore_performance_timeout_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (puts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (gets != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_prioritize.c b/3rd_party/threadx/common/src/tx_semaphore_prioritize.c new file mode 100644 index 00000000..a7f8e40d --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_prioritize.c @@ -0,0 +1,253 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the highest priority suspended thread at the */ +/* front of the suspension list. All other threads remain in the same */ +/* FIFO suspension order. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_THREAD *priority_thread_ptr; +TX_THREAD *head_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT list_changed; + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PRIORITIZE, semaphore_ptr, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_PRIORITIZE_INSERT + + /* Pickup the suspended count. */ + suspended_count = semaphore_ptr -> tx_semaphore_suspended_count; + + /* Determine if there are fewer than 2 suspended threads. */ + if (suspended_count < ((UINT) 2)) + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Determine if there how many threads are suspended on this semaphore. */ + else if (suspended_count == ((UINT) 2)) + { + + /* Pickup the head pointer and the next pointer. */ + head_ptr = semaphore_ptr -> tx_semaphore_suspension_list; + next_thread = head_ptr -> tx_thread_suspended_next; + + /* Determine if the next suspended thread has a higher priority. */ + if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority)) + { + + /* Yes, move the list head to the next thread. */ + semaphore_ptr -> tx_semaphore_suspension_list = next_thread; + } + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Remember the suspension count and head pointer. */ + head_ptr = semaphore_ptr -> tx_semaphore_suspension_list; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Set the list changed flag to false. */ + list_changed = TX_FALSE; + + /* Search through the list to find the highest priority thread. */ + do + { + + /* Is the current thread higher priority? */ + if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority) + { + + /* Yes, remember that this thread is the highest priority. */ + priority_thread_ptr = thread_ptr; + } + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Determine if any changes to the list have occurred while + interrupts were enabled. */ + + /* Is the list head the same? */ + if (head_ptr != semaphore_ptr -> tx_semaphore_suspension_list) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + else + { + + /* Is the suspended count the same? */ + if (suspended_count != semaphore_ptr -> tx_semaphore_suspended_count) + { + + /* The list head has changed, set the list changed flag. */ + list_changed = TX_TRUE; + } + } + + /* Determine if the list has changed. */ + if (list_changed == TX_FALSE) + { + + /* Yes, everything is the same... move the thread pointer to the next thread. */ + thread_ptr = thread_ptr -> tx_thread_suspended_next; + } + else + { + + /* No, the list is been modified so we need to start the search over. */ + + /* Save the suspension count and head pointer. */ + head_ptr = semaphore_ptr -> tx_semaphore_suspension_list; + suspended_count = semaphore_ptr -> tx_semaphore_suspended_count; + + /* Default the highest priority thread to the thread at the front of the list. */ + priority_thread_ptr = head_ptr; + + /* Setup search pointer. */ + thread_ptr = priority_thread_ptr -> tx_thread_suspended_next; + + /* Reset the list changed flag. */ + list_changed = TX_FALSE; + } + + } while (thread_ptr != head_ptr); + + /* Release preemption. */ + _tx_thread_preempt_disable--; + + /* Now determine if the highest priority thread is at the front + of the list. */ + if (priority_thread_ptr != head_ptr) + { + + /* No, we need to move the highest priority suspended thread to the + front of the list. */ + + /* First, remove the highest priority thread by updating the + adjacent suspended threads. */ + next_thread = priority_thread_ptr -> tx_thread_suspended_next; + previous_thread = priority_thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + + /* Now, link the highest priority thread at the front of the list. */ + previous_thread = head_ptr -> tx_thread_suspended_previous; + priority_thread_ptr -> tx_thread_suspended_next = head_ptr; + priority_thread_ptr -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = priority_thread_ptr; + head_ptr -> tx_thread_suspended_previous = priority_thread_ptr; + + /* Move the list head pointer to the highest priority suspended thread. */ + semaphore_ptr -> tx_semaphore_suspension_list = priority_thread_ptr; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_put.c b/3rd_party/threadx/common/src/tx_semaphore_put.c new file mode 100644 index 00000000..53db1a8b --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_put.c @@ -0,0 +1,224 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_put PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function puts an instance into the specified counting */ +/* semaphore. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Success completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread service */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr); +#endif + +TX_THREAD *thread_ptr; +UINT suspended_count; +TX_THREAD *next_thread; +TX_THREAD *previous_thread; + + + /* Disable interrupts to put an instance back to the semaphore. */ + TX_DISABLE + +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + + /* Increment the total semaphore put counter. */ + _tx_semaphore_performance_put_count++; + + /* Increment the number of puts on this semaphore. */ + semaphore_ptr -> tx_semaphore_performance_put_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS) + + /* Log this kernel call. */ + TX_EL_SEMAPHORE_PUT_INSERT + + /* Pickup the number of suspended threads. */ + suspended_count = semaphore_ptr -> tx_semaphore_suspended_count; + + /* Determine if there are any threads suspended on the semaphore. */ + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Increment the semaphore count. */ + semaphore_ptr -> tx_semaphore_count++; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the application notify function. */ + semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify; +#endif + + /* Restore interrupts. */ + TX_RESTORE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if notification is required. */ + if (semaphore_put_notify != TX_NULL) + { + + /* Yes, call the appropriate notify callback function. */ + (semaphore_put_notify)(semaphore_ptr); + } +#endif + } + else + { + + /* A thread is suspended on this semaphore. */ + + /* Pickup the pointer to the first suspended thread. */ + thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list; + + /* Remove the suspended thread from the list. */ + + /* See if this is the only suspended thread on the list. */ + suspended_count--; + if (suspended_count == TX_NO_SUSPENSIONS) + { + + /* Yes, the only suspended thread. */ + + /* Update the head pointer. */ + semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL; + } + else + { + + /* At least one more thread is on the same expiration list. */ + + /* Update the list head pointer. */ + next_thread = thread_ptr -> tx_thread_suspended_next; + semaphore_ptr -> tx_semaphore_suspension_list = next_thread; + + /* Update the links of the adjacent threads. */ + previous_thread = thread_ptr -> tx_thread_suspended_previous; + next_thread -> tx_thread_suspended_previous = previous_thread; + previous_thread -> tx_thread_suspended_next = next_thread; + } + + /* Decrement the suspension count. */ + semaphore_ptr -> tx_semaphore_suspended_count = suspended_count; + + /* Prepare for resumption of the first thread. */ + + /* Clear cleanup routine to avoid timeout. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the application notify function. */ + semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify; +#endif + + /* Put return status into the thread control block. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Resume thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Determine if notification is required. */ + if (semaphore_put_notify != TX_NULL) + { + + /* Yes, call the appropriate notify callback function. */ + (semaphore_put_notify)(semaphore_ptr); + } +#endif + } + + /* Return successful completion. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_semaphore_put_notify.c b/3rd_party/threadx/common/src/tx_semaphore_put_notify.c new file mode 100644 index 00000000..5fb7c709 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_semaphore_put_notify.c @@ -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 */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_put_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers an application callback function that is */ +/* called whenever the this semaphore is put. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore */ +/* semaphore_put_notify Application callback function */ +/* (TX_NULL disables notify) */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)) +{ + +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + + TX_SEMAPHORE_NOT_USED(semaphore_ptr); + TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(semaphore_put_notify); + + /* Feature is not enabled, return error. */ + return(TX_FEATURE_NOT_ENABLED); +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Make entry in event log. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT_NOTIFY, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS) + + /* Make entry in event log. */ + TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT + + /* Setup semaphore put notification callback function. */ + semaphore_ptr -> tx_semaphore_put_notify = semaphore_put_notify; + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success to caller. */ + return(TX_SUCCESS); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_thread_create.c b/3rd_party/threadx/common/src/tx_thread_create.c new file mode 100644 index 00000000..8d05e583 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_create.c @@ -0,0 +1,364 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_initialize.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a thread and places it on the list of created */ +/* threads. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* name Pointer to thread name string */ +/* entry_function Entry function of the thread */ +/* entry_input 32-bit input value to thread */ +/* stack_start Pointer to start of stack */ +/* stack_size Stack size in bytes */ +/* priority Priority of thread */ +/* (default 0-31) */ +/* preempt_threshold Preemption threshold */ +/* time_slice Thread time-slice value */ +/* auto_start Automatic start selection */ +/* */ +/* OUTPUT */ +/* */ +/* return status Thread create return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_stack_build Build initial thread stack */ +/* _tx_thread_system_resume Resume automatic start thread */ +/* _tx_thread_system_ni_resume Noninterruptable resume thread*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* _tx_timer_initialize Create system timer thread */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 William E. Lamie Modified comment(s), and */ +/* changed stack calculations */ +/* to use ALIGN_TYPE integers, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input, + VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, + ULONG time_slice, UINT auto_start) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +TX_THREAD *saved_thread_ptr; +UINT saved_threshold = ((UINT) 0); +UCHAR *temp_ptr; + +#ifdef TX_ENABLE_STACK_CHECKING +ALIGN_TYPE new_stack_start; +ALIGN_TYPE updated_stack_start; +#endif + +#ifndef TX_DISABLE_STACK_FILLING + + /* Set the thread stack to a pattern prior to creating the initial + stack frame. This pattern is used by the stack checking routines + to see how much has been used. */ + TX_MEMSET(stack_start, ((UCHAR) TX_STACK_FILL), stack_size); +#endif + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Ensure that there are two ULONG of 0xEF patterns at the top and + bottom of the thread's stack. This will be used to check for stack + overflow conditions during run-time. */ + stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG)); + + /* Ensure the starting stack address is evenly aligned. */ + new_stack_start = TX_POINTER_TO_ALIGN_TYPE_CONVERT(stack_start); + updated_stack_start = ((((ULONG) new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1)))); + + /* Determine if the starting stack address is different. */ + if (new_stack_start != updated_stack_start) + { + + /* Yes, subtract another ULONG from the size to avoid going past the stack area. */ + stack_size = stack_size - (sizeof(ULONG)); + } + + /* Update the starting stack pointer. */ + stack_start = TX_ALIGN_TYPE_TO_POINTER_CONVERT(updated_stack_start); +#endif + + /* Prepare the thread control block prior to placing it on the created + list. */ + + /* Initialize thread control block to all zeros. */ + TX_MEMSET(thread_ptr, 0, (sizeof(TX_THREAD))); + + /* Place the supplied parameters into the thread's control block. */ + thread_ptr -> tx_thread_name = name_ptr; + thread_ptr -> tx_thread_entry = entry_function; + thread_ptr -> tx_thread_entry_parameter = entry_input; + thread_ptr -> tx_thread_stack_start = stack_start; + thread_ptr -> tx_thread_stack_size = stack_size; + thread_ptr -> tx_thread_priority = priority; + thread_ptr -> tx_thread_user_priority = priority; + thread_ptr -> tx_thread_time_slice = time_slice; + thread_ptr -> tx_thread_new_time_slice = time_slice; + thread_ptr -> tx_thread_inherit_priority = ((UINT) TX_MAX_PRIORITIES); + + /* Calculate the end of the thread's stack area. */ + temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(stack_start); + temp_ptr = (TX_UCHAR_POINTER_ADD(temp_ptr, (stack_size - ((ULONG) 1)))); + thread_ptr -> tx_thread_stack_end = TX_UCHAR_TO_VOID_POINTER_CONVERT(temp_ptr); + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Preemption-threshold is enabled, setup accordingly. */ + thread_ptr -> tx_thread_preempt_threshold = preempt_threshold; + thread_ptr -> tx_thread_user_preempt_threshold = preempt_threshold; +#else + + /* Preemption-threshold is disabled, determine if preemption-threshold was required. */ + if (priority != preempt_threshold) + { + + /* Preemption-threshold specified. Since specific preemption-threshold is not supported, + disable all preemption. */ + thread_ptr -> tx_thread_preempt_threshold = ((UINT) 0); + thread_ptr -> tx_thread_user_preempt_threshold = ((UINT) 0); + } + else + { + + /* Preemption-threshold is not specified, just setup with the priority. */ + thread_ptr -> tx_thread_preempt_threshold = priority; + thread_ptr -> tx_thread_user_preempt_threshold = priority; + } +#endif + + /* Now fill in the values that are required for thread initialization. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + + /* Setup the necessary fields in the thread timer block. */ + TX_THREAD_CREATE_TIMEOUT_SETUP(thread_ptr) + + /* Perform any additional thread setup activities for tool or user purpose. */ + TX_THREAD_CREATE_INTERNAL_EXTENSION(thread_ptr) + + /* Call the target specific stack frame building routine to build the + thread's initial stack and to setup the actual stack pointer in the + control block. */ + _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry); + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Setup the highest usage stack pointer. */ + thread_ptr -> tx_thread_stack_highest_ptr = thread_ptr -> tx_thread_stack_ptr; +#endif + + /* Prepare to make this thread a member of the created thread list. */ + TX_DISABLE + + /* Load the thread ID field in the thread control block. */ + thread_ptr -> tx_thread_id = TX_THREAD_ID; + + /* Place the thread on the list of created threads. First, + check for an empty list. */ + if (_tx_thread_created_count == TX_EMPTY) + { + + /* The created thread list is empty. Add thread to empty list. */ + _tx_thread_created_ptr = thread_ptr; + thread_ptr -> tx_thread_created_next = thread_ptr; + thread_ptr -> tx_thread_created_previous = thread_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_thread = _tx_thread_created_ptr; + previous_thread = next_thread -> tx_thread_created_previous; + + /* Place the new thread in the list. */ + next_thread -> tx_thread_created_previous = thread_ptr; + previous_thread -> tx_thread_created_next = thread_ptr; + + /* Setup this thread's created links. */ + thread_ptr -> tx_thread_created_previous = previous_thread; + thread_ptr -> tx_thread_created_next = next_thread; + } + + /* Increment the thread created count. */ + _tx_thread_created_count++; + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, name_ptr, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_CREATE, thread_ptr, priority, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size, TX_TRACE_THREAD_EVENTS) + + /* Register thread in the thread array structure. */ + TX_EL_THREAD_REGISTER(thread_ptr) + + /* Log this kernel call. */ + TX_EL_THREAD_CREATE_INSERT + +#ifndef TX_NOT_INTERRUPTABLE + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; +#endif + + /* Determine if an automatic start was requested. If so, call the resume + thread function and then check for a preemption condition. */ + if (auto_start == TX_AUTO_START) + { + + /* Determine if the create call is being called from initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS) + { + + /* Yes, this create call was made from initialization. */ + + /* Pickup the current thread execute pointer, which corresponds to the + highest priority thread ready to execute. Interrupt lockout is + not required, since interrupts are assumed to be disabled during + initialization. */ + saved_thread_ptr = _tx_thread_execute_ptr; + + /* Determine if there is thread ready for execution. */ + if (saved_thread_ptr != TX_NULL) + { + + /* Yes, a thread is ready for execution when initialization completes. */ + + /* Save the current preemption-threshold. */ + saved_threshold = saved_thread_ptr -> tx_thread_preempt_threshold; + + /* For initialization, temporarily set the preemption-threshold to the + priority level to make sure the highest-priority thread runs once + initialization is complete. */ + saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority; + } + } + else + { + + /* Simply set the saved thread pointer to NULL. */ + saved_thread_ptr = TX_NULL; + } + +#ifdef TX_NOT_INTERRUPTABLE + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_CREATE_EXTENSION(thread_ptr) + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore previous interrupt posture. */ + TX_RESTORE +#else + + /* Restore previous interrupt posture. */ + TX_RESTORE + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_CREATE_EXTENSION(thread_ptr) + + /* Call the resume thread function to make this thread ready. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Determine if the thread's preemption-threshold needs to be restored. */ + if (saved_thread_ptr != TX_NULL) + { + + /* Yes, restore the previous highest-priority thread's preemption-threshold. This + can only happen if this routine is called from initialization. */ + saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold; + } + } + else + { + +#ifdef TX_NOT_INTERRUPTABLE + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_CREATE_EXTENSION(thread_ptr) + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Restore interrupts. */ + TX_RESTORE + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_CREATE_EXTENSION(thread_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Re-enable preemption. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); +#endif + } + + /* Always return a success. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_delete.c b/3rd_party/threadx/common/src/tx_thread_delete.c new file mode 100644 index 00000000..eaa3aa62 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_delete.c @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles application delete thread requests. The */ +/* thread to delete must be in a terminated or completed state, */ +/* otherwise this function just returns an error code. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* status Return completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_delete(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *next_thread; +TX_THREAD *previous_thread; +UINT status; + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Lockout interrupts while the thread is being deleted. */ + TX_DISABLE + + /* Check for proper status of this thread to delete. */ + if (thread_ptr -> tx_thread_state != TX_COMPLETED) + { + + /* Now check for terminated state. */ + if (thread_ptr -> tx_thread_state != TX_TERMINATED) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Thread not completed or terminated - return an error! */ + status = TX_DELETE_ERROR; + } + } + + /* Determine if the delete operation is okay. */ + if (status == TX_SUCCESS) + { + + /* Yes, continue with deleting the thread. */ + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_DELETE_EXTENSION(thread_ptr) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_DELETE, thread_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_thread), 0, 0, TX_TRACE_THREAD_EVENTS) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(thread_ptr) + + /* Log this kernel call. */ + TX_EL_THREAD_DELETE_INSERT + + /* Unregister thread in the thread array structure. */ + TX_EL_THREAD_UNREGISTER(thread_ptr) + + /* Clear the thread ID to make it invalid. */ + thread_ptr -> tx_thread_id = TX_CLEAR_ID; + + /* Decrement the number of created threads. */ + _tx_thread_created_count--; + + /* See if the thread is the only one on the list. */ + if (_tx_thread_created_count == TX_EMPTY) + { + + /* Only created thread, just set the created list to NULL. */ + _tx_thread_created_ptr = TX_NULL; + } + else + { + + /* Otherwise, not the only created thread, link-up the neighbors. */ + next_thread = thread_ptr -> tx_thread_created_next; + previous_thread = thread_ptr -> tx_thread_created_previous; + next_thread -> tx_thread_created_previous = previous_thread; + previous_thread -> tx_thread_created_next = next_thread; + + /* See if we have to update the created list head pointer. */ + if (_tx_thread_created_ptr == thread_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_thread_created_ptr = next_thread; + } + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr) + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_entry_exit_notify.c b/3rd_party/threadx/common/src/tx_thread_entry_exit_notify.c new file mode 100644 index 00000000..b8c69a61 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_entry_exit_notify.c @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_entry_exit_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers an application entry/exit notification */ +/* callback routine for the application. Once registered, the callback */ +/* routine is called when the thread is initially entered and called */ +/* again when the thread completes or is terminated. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread */ +/* thread_entry_exit_notify Pointer to notify callback */ +/* function, TX_NULL to disable*/ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)) +{ + +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + + TX_THREAD_NOT_USED(thread_ptr); + TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(thread_entry_exit_notify); + + /* Feature is not enabled, return error. */ + return(TX_FEATURE_NOT_ENABLED); +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Make entry in event log. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Make entry in event log. */ + TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT + + /* Setup thread entry/exit notification callback function. */ + thread_ptr -> tx_thread_entry_exit_notify = thread_entry_exit_notify; + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success to caller. */ + return(TX_SUCCESS); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_thread_identify.c b/3rd_party/threadx/common/src/tx_thread_identify.c new file mode 100644 index 00000000..2b833b97 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_identify.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_trace.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_identify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the control block pointer of the currently */ +/* executing thread. If the return value is NULL, no thread is */ +/* executing. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD * Pointer to control block of */ +/* currently executing thread */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +TX_THREAD *_tx_thread_identify(VOID) +{ + +TX_THREAD *thread_ptr; + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts to put the timer on the created list. */ + TX_DISABLE + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_IDENTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS) +#endif + + /* Log this kernel call. */ + TX_EL_THREAD_IDENTIFY_INSERT + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Restore interrupts. */ + TX_RESTORE + + /* Return the current thread pointer. */ + return(thread_ptr); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_info_get.c b/3rd_party/threadx/common/src/tx_thread_info_get.c new file mode 100644 index 00000000..d12c0dcc --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_info_get.c @@ -0,0 +1,165 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified thread. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control block */ +/* name Destination for the thread name */ +/* state Destination for thread state */ +/* run_count Destination for thread run count */ +/* priority Destination for thread priority */ +/* preemption_threshold Destination for thread preemption-*/ +/* threshold */ +/* time_slice Destination for thread time-slice */ +/* next_thread Destination for next created */ +/* thread */ +/* next_suspended_thread Destination for next suspended */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, + UINT *priority, UINT *preemption_threshold, ULONG *time_slice, + TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve the name of the thread. */ + if (name != TX_NULL) + { + + *name = thread_ptr -> tx_thread_name; + } + + /* Pickup the thread's current state. */ + if (state != TX_NULL) + { + + *state = thread_ptr -> tx_thread_state; + } + + /* Pickup the number of times the thread has been scheduled. */ + if (run_count != TX_NULL) + { + + *run_count = thread_ptr -> tx_thread_run_count; + } + + /* Pickup the thread's priority. */ + if (priority != TX_NULL) + { + + *priority = thread_ptr -> tx_thread_user_priority; + } + + /* Pickup the thread's preemption-threshold. */ + if (preemption_threshold != TX_NULL) + { + + *preemption_threshold = thread_ptr -> tx_thread_user_preempt_threshold; + } + + /* Pickup the thread's current time-slice. */ + if (time_slice != TX_NULL) + { + + *time_slice = thread_ptr -> tx_thread_time_slice; + } + + /* Pickup the next created thread. */ + if (next_thread != TX_NULL) + { + + *next_thread = thread_ptr -> tx_thread_created_next; + } + + /* Pickup the next thread suspended. */ + if (next_suspended_thread != TX_NULL) + { + + *next_suspended_thread = thread_ptr -> tx_thread_suspended_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_initialize.c b/3rd_party/threadx/common/src/tx_thread_initialize.c new file mode 100644 index 00000000..cd4a047d --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_initialize.c @@ -0,0 +1,450 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +#ifndef TX_MISRA_ENABLE +#define TX_THREAD_INIT +#endif + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + + +/* Define the pointer that contains the system stack pointer. This is + utilized when control returns from a thread to the system to reset the + current stack. This is setup in the low-level initialization function. */ + +VOID * _tx_thread_system_stack_ptr; + + +/* Define the current thread pointer. This variable points to the currently + executing thread. If this variable is NULL, no thread is executing. */ + +TX_THREAD * _tx_thread_current_ptr; + + +/* Define the variable that holds the next thread to execute. It is important + to remember that this is not necessarily equal to the current thread + pointer. */ + +TX_THREAD * _tx_thread_execute_ptr; + + +/* Define the head pointer of the created thread list. */ + +TX_THREAD * _tx_thread_created_ptr; + + +/* Define the variable that holds the number of created threads. */ + +ULONG _tx_thread_created_count; + + +/* Define the current state variable. When this value is 0, a thread + is executing or the system is idle. Other values indicate that + interrupt or initialization processing is active. This variable is + initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is + active. */ + +volatile ULONG _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS; + + +/* Define the 32-bit priority bit-maps. There is one priority bit map for each + 32 priority levels supported. If only 32 priorities are supported there is + only one bit map. Each bit within a priority bit map represents that one + or more threads at the associated thread priority are ready. */ + +ULONG _tx_thread_priority_maps[TX_MAX_PRIORITIES/32]; + + +/* Define the priority map active bit map that specifies which of the previously + defined priority maps have something set. This is only necessary if more than + 32 priorities are supported. */ + +#if TX_MAX_PRIORITIES > 32 +ULONG _tx_thread_priority_map_active; +#endif + + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +/* Define the 32-bit preempt priority bit maps. There is one preempt bit map + for each 32 priority levels supported. If only 32 priorities are supported + there is only one bit map. Each set set bit corresponds to a preempted priority + level that had preemption-threshold active to protect against preemption of a + range of relatively higher priority threads. */ + +ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32]; + + +/* Define the preempt map active bit map that specifies which of the previously + defined preempt maps have something set. This is only necessary if more than + 32 priorities are supported. */ + +#if TX_MAX_PRIORITIES > 32 +ULONG _tx_thread_preempted_map_active; +#endif +#endif + +/* Define the variable that holds the highest priority group ready for + execution. It is important to note that this is not necessarily the same + as the priority of the thread pointed to by _tx_execute_thread. */ + +UINT _tx_thread_highest_priority; + + +/* Define the array of thread pointers. Each entry represents the threads that + are ready at that priority group. For example, index 10 in this array + represents the first thread ready at priority 10. If this entry is NULL, + no threads are ready at that priority. */ + +TX_THREAD * _tx_thread_priority_list[TX_MAX_PRIORITIES]; + + +/* Define the global preempt disable variable. If this is non-zero, preemption is + disabled. It is used internally by ThreadX to prevent preemption of a thread in + the middle of a service that is resuming or suspending another thread. */ + +volatile UINT _tx_thread_preempt_disable; + + +/* Define the global function pointer for mutex cleanup on thread completion or + termination. This pointer is setup during mutex initialization. */ + +VOID (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr); + + +/* Define the global build options variable. This contains a bit map representing + how the ThreadX library was built. The following are the bit field definitions: + + Bit(s) Meaning + + 31 TX_NOT_INTERRUPTABLE defined + 30 TX_INLINE_THREAD_RESUME_SUSPEND define + 29-24 Priority groups 1 -> 32 priorities + 2 -> 64 priorities + 3 -> 96 priorities + + ... + + 32 -> 1024 priorities + 23 TX_TIMER_PROCESS_IN_ISR defined + 22 TX_REACTIVATE_INLINE defined + 21 TX_DISABLE_STACK_FILLING defined + 20 TX_ENABLE_STACK_CHECKING defined + 19 TX_DISABLE_PREEMPTION_THRESHOLD defined + 18 TX_DISABLE_REDUNDANT_CLEARING defined + 17 TX_DISABLE_NOTIFY_CALLBACKS defined + 16 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined + 15 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined + 14 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined + 13 TX_MUTEX_ENABLE_PERFORMANCE_INFO defined + 12 TX_QUEUE_ENABLE_PERFORMANCE_INFO defined + 11 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined + 10 TX_THREAD_ENABLE_PERFORMANCE_INFO defined + 9 TX_TIMER_ENABLE_PERFORMANCE_INFO defined + 8 TX_ENABLE_EVENT_TRACE defined + 7 TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined + 6-0 Port Specific */ + +ULONG _tx_build_options; + + +#ifdef TX_ENABLE_STACK_CHECKING + +/* Define the global function pointer for stack error handling. If a stack error is + detected and the application has registered a stack error handler, it will be + called via this function pointer. */ + +VOID (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr); + +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + +/* Define the total number of thread resumptions. Each time a thread enters the + ready state this variable is incremented. */ + +ULONG _tx_thread_performance_resume_count; + + +/* Define the total number of thread suspensions. Each time a thread enters a + suspended state this variable is incremented. */ + +ULONG _tx_thread_performance_suspend_count; + + +/* Define the total number of solicited thread preemptions. Each time a thread is + preempted by directly calling a ThreadX service, this variable is incremented. */ + +ULONG _tx_thread_performance_solicited_preemption_count; + + +/* Define the total number of interrupt thread preemptions. Each time a thread is + preempted as a result of an ISR calling a ThreadX service, this variable is + incremented. */ + +ULONG _tx_thread_performance_interrupt_preemption_count; + + +/* Define the total number of priority inversions. Each time a thread is blocked by + a mutex owned by a lower-priority thread, this variable is incremented. */ + +ULONG _tx_thread_performance_priority_inversion_count; + + +/* Define the total number of time-slices. Each time a time-slice operation is + actually performed (another thread is setup for running) this variable is + incremented. */ + +ULONG _tx_thread_performance_time_slice_count; + + +/* Define the total number of thread relinquish operations. Each time a thread + relinquish operation is actually performed (another thread is setup for running) + this variable is incremented. */ + +ULONG _tx_thread_performance_relinquish_count; + + +/* Define the total number of thread timeouts. Each time a thread has a + timeout this variable is incremented. */ + +ULONG _tx_thread_performance_timeout_count; + + +/* Define the total number of thread wait aborts. Each time a thread's suspension + is lifted by the tx_thread_wait_abort call this variable is incremented. */ + +ULONG _tx_thread_performance_wait_abort_count; + + +/* Define the total number of idle system thread returns. Each time a thread returns to + an idle system (no other thread is ready to run) this variable is incremented. */ + +ULONG _tx_thread_performance_idle_return_count; + + +/* Define the total number of non-idle system thread returns. Each time a thread returns to + a non-idle system (another thread is ready to run) this variable is incremented. */ + +ULONG _tx_thread_performance_non_idle_return_count; + + +/* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This + is a circular list, where the index points to the oldest entry. */ + +ULONG _tx_thread_performance__execute_log_index; +TX_THREAD * _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE]; +#endif + + +/* Define special string. */ + +#ifndef TX_MISRA_ENABLE +const CHAR _tx_thread_special_string[] = + "G-ML-EL-ML-BL-DL-BL-GB-GL-M-D-DL-GZ-KH-EL-CM-NH-HA-GF-DD-JC-YZ-CT-AT-DW-USA-CA-SD-SDSU"; +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the thread control component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_initialize(VOID) +{ + + /* Note: the system stack pointer and the system state variables are + initialized by the low and high-level initialization functions, + respectively. */ + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Set current thread pointer to NULL. */ + TX_THREAD_SET_CURRENT(TX_NULL) + + /* Initialize the execute thread pointer to NULL. */ + _tx_thread_execute_ptr = TX_NULL; + + /* Initialize the priority information. */ + TX_MEMSET(&_tx_thread_priority_maps[0], 0, (sizeof(_tx_thread_priority_maps))); + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + TX_MEMSET(&_tx_thread_preempted_maps[0], 0, (sizeof(_tx_thread_preempted_maps))); +#endif +#endif + + /* Setup the highest priority variable to the max, indicating no thread is currently + ready. */ + _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES); + + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the array of priority head pointers. */ + TX_MEMSET(&_tx_thread_priority_list[0], 0, (sizeof(_tx_thread_priority_list))); + + /* Initialize the head pointer of the created threads list and the + number of threads created. */ + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = TX_EMPTY; + + /* Clear the global preempt disable variable. */ + _tx_thread_preempt_disable = ((UINT) 0); + + /* Initialize the thread mutex release function pointer. */ + _tx_thread_mutex_release = TX_NULL; + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Clear application registered stack error handler. */ + _tx_thread_application_stack_error_handler = TX_NULL; +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Clear performance counters. */ + _tx_thread_performance_resume_count = ((ULONG) 0); + _tx_thread_performance_suspend_count = ((ULONG) 0); + _tx_thread_performance_solicited_preemption_count = ((ULONG) 0); + _tx_thread_performance_interrupt_preemption_count = ((ULONG) 0); + _tx_thread_performance_priority_inversion_count = ((ULONG) 0); + _tx_thread_performance_time_slice_count = ((ULONG) 0); + _tx_thread_performance_relinquish_count = ((ULONG) 0); + _tx_thread_performance_timeout_count = ((ULONG) 0); + _tx_thread_performance_wait_abort_count = ((ULONG) 0); + _tx_thread_performance_idle_return_count = ((ULONG) 0); + _tx_thread_performance_non_idle_return_count = ((ULONG) 0); + + /* Initialize the execute thread log. */ + TX_MEMSET(&_tx_thread_performance_execute_log[0], 0, (sizeof(_tx_thread_performance_execute_log))); +#endif +#endif + + /* Setup the build options flag. This is used to identify how the ThreadX library was constructed. */ + _tx_build_options = _tx_build_options + | (((ULONG) (TX_MAX_PRIORITIES/32)) << 24) +#ifdef TX_NOT_INTERRUPTABLE + | (((ULONG) 1) << 31) +#endif +#ifdef TX_INLINE_THREAD_RESUME_SUSPEND + | (((ULONG) 1) << 30) +#endif +#ifdef TX_TIMER_PROCESS_IN_ISR + | (((ULONG) 1) << 23) +#endif +#ifdef TX_REACTIVATE_INLINE + | (((ULONG) 1) << 22) +#endif +#ifdef TX_DISABLE_STACK_FILLING + | (((ULONG) 1) << 21) +#endif +#ifdef TX_ENABLE_STACK_CHECKING + | (((ULONG) 1) << 20) +#endif +#ifdef TX_DISABLE_PREEMPTION_THRESHOLD + | (((ULONG) 1) << 19) +#endif +#ifdef TX_DISABLE_REDUNDANT_CLEARING + | (((ULONG) 1) << 18) +#endif +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + | (((ULONG) 1) << 17) +#endif +#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 16) +#endif +#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 15) +#endif +#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 14) +#endif +#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 13) +#endif +#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 12) +#endif +#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 11) +#endif +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 10) +#endif +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + | (((ULONG) 1) << 9) +#endif +#ifdef TX_ENABLE_EVENT_TRACE + | (((ULONG) 1) << 8) +#endif +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + | (((ULONG) 1) << 7) +#endif +#if TX_PORT_SPECIFIC_BUILD_OPTIONS != 0 + | TX_PORT_SPECIFIC_BUILD_OPTIONS +#endif + ; +} + diff --git a/3rd_party/threadx/common/src/tx_thread_performance_info_get.c b/3rd_party/threadx/common/src/tx_thread_performance_info_get.c new file mode 100644 index 00000000..737e1611 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_performance_info_get.c @@ -0,0 +1,299 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* thread. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control block */ +/* resumptions Destination for number of times */ +/* thread was resumed */ +/* suspensions Destination for number of times */ +/* thread was suspended */ +/* solicited_preemptions Destination for number of times */ +/* thread called another service */ +/* that resulted in preemption */ +/* interrupt_preemptions Destination for number of times */ +/* thread was preempted by another */ +/* thread made ready in Interrupt */ +/* Service Routine (ISR) */ +/* priority_inversions Destination for number of times */ +/* a priority inversion was */ +/* detected for this thread */ +/* time_slices Destination for number of times */ +/* thread was time-sliced */ +/* relinquishes Destination for number of thread */ +/* relinquishes */ +/* timeouts Destination for number of timeouts*/ +/* for thread */ +/* wait_aborts Destination for number of wait */ +/* aborts for thread */ +/* last_preempted_by Destination for pointer of the */ +/* thread that last preempted this */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_performance_info_get(TX_THREAD *thread_ptr, ULONG *resumptions, ULONG *suspensions, + ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions, + ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts, TX_THREAD **last_preempted_by) +{ + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Determine if this is a legal request. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the thread ID is invalid. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PERFORMANCE_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve number of resumptions for this thread. */ + if (resumptions != TX_NULL) + { + + *resumptions = thread_ptr -> tx_thread_performance_resume_count; + } + + /* Retrieve number of suspensions for this thread. */ + if (suspensions != TX_NULL) + { + + *suspensions = thread_ptr -> tx_thread_performance_suspend_count; + } + + /* Retrieve number of solicited preemptions for this thread. */ + if (solicited_preemptions != TX_NULL) + { + + *solicited_preemptions = thread_ptr -> tx_thread_performance_solicited_preemption_count; + } + + /* Retrieve number of interrupt preemptions for this thread. */ + if (interrupt_preemptions != TX_NULL) + { + + *interrupt_preemptions = thread_ptr -> tx_thread_performance_interrupt_preemption_count; + } + + /* Retrieve number of priority inversions for this thread. */ + if (priority_inversions != TX_NULL) + { + + *priority_inversions = thread_ptr -> tx_thread_performance_priority_inversion_count; + } + + /* Retrieve number of time-slices for this thread. */ + if (time_slices != TX_NULL) + { + + *time_slices = thread_ptr -> tx_thread_performance_time_slice_count; + } + + /* Retrieve number of relinquishes for this thread. */ + if (relinquishes != TX_NULL) + { + + *relinquishes = thread_ptr -> tx_thread_performance_relinquish_count; + } + + /* Retrieve number of timeouts for this thread. */ + if (timeouts != TX_NULL) + { + + *timeouts = thread_ptr -> tx_thread_performance_timeout_count; + } + + /* Retrieve number of wait aborts for this thread. */ + if (wait_aborts != TX_NULL) + { + + *wait_aborts = thread_ptr -> tx_thread_performance_wait_abort_count; + } + + /* Retrieve the pointer of the last thread that preempted this thread. */ + if (last_preempted_by != TX_NULL) + { + + *last_preempted_by = thread_ptr -> tx_thread_performance_last_preempting_thread; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + status = TX_SUCCESS; + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (thread_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (resumptions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (solicited_preemptions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (interrupt_preemptions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (priority_inversions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (time_slices != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (relinquishes != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (wait_aborts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (last_preempted_by != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_thread_performance_system_info_get.c new file mode 100644 index 00000000..8c0afb43 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_performance_system_info_get.c @@ -0,0 +1,289 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves thread system performance information. */ +/* */ +/* INPUT */ +/* */ +/* resumptions Destination for total number of */ +/* thread resumptions */ +/* suspensions Destination for total number of */ +/* thread suspensions */ +/* solicited_preemptions Destination for total number of */ +/* thread preemption from thread */ +/* API calls */ +/* interrupt_preemptions Destination for total number of */ +/* thread preemptions as a result */ +/* of threads made ready inside of */ +/* Interrupt Service Routines */ +/* priority_inversions Destination for total number of */ +/* priority inversions */ +/* time_slices Destination for total number of */ +/* time-slices */ +/* relinquishes Destination for total number of */ +/* relinquishes */ +/* timeouts Destination for total number of */ +/* timeouts */ +/* wait_aborts Destination for total number of */ +/* wait aborts */ +/* non_idle_returns Destination for total number of */ +/* times threads return when */ +/* another thread is ready */ +/* idle_returns Destination for total number of */ +/* times threads return when no */ +/* other thread is ready */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_performance_system_info_get(ULONG *resumptions, ULONG *suspensions, + ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions, + ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts, + ULONG *non_idle_returns, ULONG *idle_returns) +{ + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Retrieve total number of thread resumptions. */ + if (resumptions != TX_NULL) + { + + *resumptions = _tx_thread_performance_resume_count; + } + + /* Retrieve total number of thread suspensions. */ + if (suspensions != TX_NULL) + { + + *suspensions = _tx_thread_performance_suspend_count; + } + + /* Retrieve total number of solicited thread preemptions. */ + if (solicited_preemptions != TX_NULL) + { + + *solicited_preemptions = _tx_thread_performance_solicited_preemption_count; + } + + /* Retrieve total number of interrupt thread preemptions. */ + if (interrupt_preemptions != TX_NULL) + { + + *interrupt_preemptions = _tx_thread_performance_interrupt_preemption_count; + } + + /* Retrieve total number of thread priority inversions. */ + if (priority_inversions != TX_NULL) + { + + *priority_inversions = _tx_thread_performance_priority_inversion_count; + } + + /* Retrieve total number of thread time-slices. */ + if (time_slices != TX_NULL) + { + + *time_slices = _tx_thread_performance_time_slice_count; + } + + /* Retrieve total number of thread relinquishes. */ + if (relinquishes != TX_NULL) + { + + *relinquishes = _tx_thread_performance_relinquish_count; + } + + /* Retrieve total number of thread timeouts. */ + if (timeouts != TX_NULL) + { + + *timeouts = _tx_thread_performance_timeout_count; + } + + /* Retrieve total number of thread wait aborts. */ + if (wait_aborts != TX_NULL) + { + + *wait_aborts = _tx_thread_performance_wait_abort_count; + } + + /* Retrieve total number of thread non-idle system returns. */ + if (non_idle_returns != TX_NULL) + { + + *non_idle_returns = _tx_thread_performance_non_idle_return_count; + } + + /* Retrieve total number of thread idle system returns. */ + if (idle_returns != TX_NULL) + { + + *idle_returns = _tx_thread_performance_idle_return_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (resumptions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (suspensions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (solicited_preemptions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (interrupt_preemptions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (priority_inversions != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (time_slices != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (relinquishes != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (timeouts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (wait_aborts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (non_idle_returns != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (idle_returns != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_thread_preemption_change.c b/3rd_party/threadx/common/src/tx_thread_preemption_change.c new file mode 100644 index 00000000..3d00793f --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_preemption_change.c @@ -0,0 +1,282 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_preemption_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes preemption-threshold change requests. The */ +/* previous preemption is returned to the caller. If the new request */ +/* allows a higher priority thread to execute, preemption takes place */ +/* inside of this function. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread */ +/* new_threshold New preemption threshold */ +/* old_threshold Old preemption threshold */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, UINT *old_threshold) +{ + +TX_INTERRUPT_SAVE_AREA + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD +ULONG priority_bit; +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif +#endif +UINT status; + + + /* Default status to success. */ + status = TX_SUCCESS; + +#ifdef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Only allow 0 (disable all preemption) and returning preemption-threshold to the + current thread priority if preemption-threshold is disabled. All other threshold + values are converted to 0. */ + if (thread_ptr -> tx_thread_user_priority != new_threshold) + { + + /* Is the new threshold zero? */ + if (new_threshold != ((UINT) 0)) + { + + /* Convert the new threshold to disable all preemption, since preemption-threshold is + not supported. */ + new_threshold = ((UINT) 0); + } + } +#endif + + /* Lockout interrupts while the thread is being resumed. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PREEMPTION_CHANGE, thread_ptr, new_threshold, thread_ptr -> tx_thread_preempt_threshold, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_PREEMPTION_CHANGE_INSERT + + /* Determine if the new threshold is greater than the current user priority. */ + if (new_threshold > thread_ptr -> tx_thread_user_priority) + { + + /* Return error. */ + status = TX_THRESH_ERROR; + } + else + { + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if the new threshold is the same as the priority. */ + if (thread_ptr -> tx_thread_user_priority == new_threshold) + { + + /* Determine if this thread is at the head of the list. */ + if (_tx_thread_priority_list[thread_ptr -> tx_thread_priority] == thread_ptr) + { + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = (thread_ptr -> tx_thread_priority)/((UINT) 32); +#endif + + /* Yes, this thread is at the front of the list. Make sure + the preempted bit is cleared for this thread. */ + TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } + } +#endif + + /* Return the user's preemption-threshold. */ + *old_threshold = thread_ptr -> tx_thread_user_preempt_threshold; + + /* Setup the new threshold. */ + thread_ptr -> tx_thread_user_preempt_threshold = new_threshold; + + /* Determine if the new threshold represents a higher priority than the priority inheritance threshold. */ + if (new_threshold < thread_ptr -> tx_thread_inherit_priority) + { + + /* Update the actual preemption-threshold with the new threshold. */ + thread_ptr -> tx_thread_preempt_threshold = new_threshold; + } + else + { + + /* Update the actual preemption-threshold with the priority inheritance. */ + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority; + } + + /* Is the thread priority less than the current highest priority? If not, no preemption is required. */ + if (_tx_thread_highest_priority < thread_ptr -> tx_thread_priority) + { + + /* Is the new thread preemption-threshold less than the current highest priority? If not, no preemption is required. */ + if (_tx_thread_highest_priority < new_threshold) + { + + /* If the current execute pointer is the same at this thread, preemption needs to take place. */ + if (_tx_thread_execute_ptr == thread_ptr) + { + + /* Preemption needs to take place. */ + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if this thread has preemption threshold set. */ + if (thread_ptr -> tx_thread_preempt_threshold != thread_ptr -> tx_thread_priority) + { + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = (thread_ptr -> tx_thread_priority)/((UINT) 32); + + /* Set the active bit to remember that the preempt map has something set. */ + TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit; +#endif + + /* Remember that this thread was preempted by a thread above the thread's threshold. */ + TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; + } +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if the caller is an interrupt or from a thread. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Caller is a thread, so this is a solicited preemption. */ + _tx_thread_performance_solicited_preemption_count++; + + /* Increment the thread's solicited preemption counter. */ + thread_ptr -> tx_thread_performance_solicited_preemption_count++; + } + + /* Remember the thread that preempted this thread. */ + thread_ptr -> tx_thread_performance_last_preempting_thread = _tx_thread_priority_list[_tx_thread_highest_priority]; + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + + /* Setup the highest priority thread to execute. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Disable interrupts. */ + TX_DISABLE + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_priority_change.c b/3rd_party/threadx/common/src/tx_thread_priority_change.c new file mode 100644 index 00000000..06b9391e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_priority_change.c @@ -0,0 +1,287 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_priority_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the priority of the specified thread. It */ +/* also returns the old priority and handles preemption if the calling */ +/* thread is currently executing and the priority change results in a */ +/* higher priority thread ready for execution. */ +/* */ +/* Note: the preemption threshold is automatically changed to the new */ +/* priority. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* new_priority New thread priority */ +/* old_priority Old thread priority */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_thread_system_suspend Suspend thread */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 William E. Lamie Modified comment(s), and */ +/* change thread state from */ +/* TX_SUSPENDED to */ +/* TX_PRIORITY_CHANGE before */ +/* calling */ +/* _tx_thread_system_suspend, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority, UINT *old_priority) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *execute_ptr; +TX_THREAD *next_execute_ptr; +UINT original_priority; + + + /* Lockout interrupts while the thread is being suspended. */ + TX_DISABLE + + /* Save the previous priority. */ + *old_priority = thread_ptr -> tx_thread_user_priority; + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PRIORITY_CHANGE, thread_ptr, new_priority, thread_ptr -> tx_thread_priority, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_PRIORITY_CHANGE_INSERT + + /* Determine if this thread is currently ready. */ + if (thread_ptr -> tx_thread_state != TX_READY) + { + + /* Setup the user priority and threshold in the thread's control + block. */ + thread_ptr -> tx_thread_user_priority = new_priority; + thread_ptr -> tx_thread_user_preempt_threshold = new_priority; + + /* Determine if the actual thread priority should be setup, which is the + case if the new priority is higher than the priority inheritance. */ + if (new_priority < thread_ptr -> tx_thread_inherit_priority) + { + + /* Change thread priority to the new user's priority. */ + thread_ptr -> tx_thread_priority = new_priority; + thread_ptr -> tx_thread_preempt_threshold = new_priority; + } + else + { + + /* Change thread priority to the priority inheritance. */ + thread_ptr -> tx_thread_priority = thread_ptr -> tx_thread_inherit_priority; + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority; + } + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Set the state to priority change. */ + thread_ptr -> tx_thread_state = TX_PRIORITY_CHANGE; + + /* Pickup the next thread to execute. */ + execute_ptr = _tx_thread_execute_ptr; + + /* Save the original priority. */ + original_priority = thread_ptr -> tx_thread_priority; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); + + /* At this point, the preempt disable flag is still set, so we still have + protection against all preemption. */ + + /* Setup the new priority for this thread. */ + thread_ptr -> tx_thread_user_priority = new_priority; + thread_ptr -> tx_thread_user_preempt_threshold = new_priority; + + /* Determine if the actual thread priority should be setup, which is the + case if the new priority is higher than the priority inheritance. */ + if (new_priority < thread_ptr -> tx_thread_inherit_priority) + { + + /* Change thread priority to the new user's priority. */ + thread_ptr -> tx_thread_priority = new_priority; + thread_ptr -> tx_thread_preempt_threshold = new_priority; + } + else + { + + /* Change thread priority to the priority inheritance. */ + thread_ptr -> tx_thread_priority = thread_ptr -> tx_thread_inherit_priority; + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority; + } + + /* Resume the thread with the new priority. */ + _tx_thread_system_ni_resume(thread_ptr); + +#else + + /* Increment the preempt disable flag by 2 to prevent system suspend from + returning to the system. */ + _tx_thread_preempt_disable = _tx_thread_preempt_disable + ((UINT) 3); + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0); + + /* Restore interrupts. */ + TX_RESTORE + + /* The thread is ready and must first be removed from the list. Call the + system suspend function to accomplish this. */ + _tx_thread_system_suspend(thread_ptr); + + /* At this point, the preempt disable flag is still set, so we still have + protection against all preemption. */ + + /* Setup the new priority for this thread. */ + thread_ptr -> tx_thread_user_priority = new_priority; + thread_ptr -> tx_thread_user_preempt_threshold = new_priority; + + /* Determine if the actual thread priority should be setup, which is the + case if the new priority is higher than the priority inheritance. */ + if (new_priority < thread_ptr -> tx_thread_inherit_priority) + { + + /* Change thread priority to the new user's priority. */ + thread_ptr -> tx_thread_priority = new_priority; + thread_ptr -> tx_thread_preempt_threshold = new_priority; + } + else + { + + /* Change thread priority to the priority inheritance. */ + thread_ptr -> tx_thread_priority = thread_ptr -> tx_thread_inherit_priority; + thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority; + } + + /* Resume the thread with the new priority. */ + _tx_thread_system_resume(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Pickup the next thread to execute. */ + next_execute_ptr = _tx_thread_execute_ptr; + + /* Determine if this thread is not the next thread to execute. */ + if (thread_ptr != next_execute_ptr) + { + + /* Make sure the thread is still ready. */ + if (thread_ptr -> tx_thread_state == TX_READY) + { + + /* Now check and see if this thread has an equal or higher priority. */ + if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority) + { + + /* Now determine if this thread was the previously executing thread. */ + if (thread_ptr == execute_ptr) + { + + /* Yes, this thread was previously executing before we temporarily suspended and resumed + it in order to change the priority. A lower or same priority thread cannot be the next thread + to execute in this case since this thread really didn't suspend. Simply reset the execute + pointer to this thread. */ + _tx_thread_execute_ptr = thread_ptr; + + /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */ + if (original_priority < new_priority) + { + + /* Ensure that this thread is placed at the front of the priority list. */ + _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr; + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + } + + /* Return success if we get here! */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_relinquish.c b/3rd_party/threadx/common/src/tx_thread_relinquish.c new file mode 100644 index 00000000..f6f6e4bc --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_relinquish.c @@ -0,0 +1,171 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#ifndef TX_NO_TIMER +#include "tx_timer.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_relinquish PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function moves the currently executing thread to the end of */ +/* the list of threads ready at the same priority. If no other threads */ +/* of the same or higher priority are ready, this function simply */ +/* returns. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_return Return to the system */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_relinquish(VOID) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT priority; +TX_THREAD *thread_ptr; + + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Disable interrupts. */ + TX_DISABLE + +#ifndef TX_NO_TIMER + + /* Reset time slice for current thread. */ + _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice; +#endif + + /* Pickup the thread's priority. */ + priority = thread_ptr -> tx_thread_priority; + + /* Determine if there is another thread at the same priority. */ + if (thread_ptr -> tx_thread_ready_next != thread_ptr) + { + + /* Yes, there is another thread at this priority, make it the highest at + this priority level. */ + _tx_thread_priority_list[priority] = thread_ptr -> tx_thread_ready_next; + + /* Mark the new thread as the one to execute. */ + _tx_thread_execute_ptr = thread_ptr -> tx_thread_ready_next; + } + + /* Determine if there is a higher-priority thread ready. */ + if (_tx_thread_highest_priority < priority) + { + + /* Yes, there is a higher priority thread ready to execute. Make + it visible to the thread scheduler. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; + + /* No need to clear the preempted bit in this case, since the currently running + thread must already have its preempted bit clear. */ + } + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RELINQUISH, &thread_ptr, TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_RELINQUISH_INSERT + + /* Restore previous interrupt posture. */ + TX_RESTORE + + /* Determine if this thread needs to return to the system. */ + if (_tx_thread_execute_ptr != thread_ptr) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the number of thread relinquishes. */ + thread_ptr -> tx_thread_performance_relinquish_count++; + + /* Increment the total number of thread relinquish operations. */ + _tx_thread_performance_relinquish_count++; + + /* Increment the non-idle return count. */ + _tx_thread_performance_non_idle_return_count++; +#endif + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Transfer control to the system so the scheduler can execute + the next thread. */ + _tx_thread_system_return(); + } +} + diff --git a/3rd_party/threadx/common/src/tx_thread_reset.c b/3rd_party/threadx/common/src/tx_thread_reset.c new file mode 100644 index 00000000..5fc97e51 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_reset.c @@ -0,0 +1,165 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_reset PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function prepares the thread to run again from the entry */ +/* point specified during thread creation. The application must */ +/* call tx_thread_resume after this call completes for the thread */ +/* to actually run. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to reset */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_stack_build Build initial thread stack */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_reset(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *current_thread; +UINT status; + + + /* Default a successful completion status. */ + status = TX_SUCCESS; + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Check for a call from the current thread, which is not allowed! */ + if (current_thread == thread_ptr) + { + + /* Thread not completed or terminated - return an error! */ + status = TX_NOT_DONE; + } + else + { + + /* Check for proper status of this thread to reset. */ + if (thread_ptr -> tx_thread_state != TX_COMPLETED) + { + + /* Now check for terminated state. */ + if (thread_ptr -> tx_thread_state != TX_TERMINATED) + { + + /* Thread not completed or terminated - return an error! */ + status = TX_NOT_DONE; + } + } + } + + /* Is the request valid? */ + if (status == TX_SUCCESS) + { + + /* Modify the thread status to prevent additional reset calls. */ + thread_ptr -> tx_thread_state = TX_NOT_DONE; + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_THREAD_RESET_PORT_COMPLETION(thread_ptr) + + /* Restore interrupts. */ + TX_RESTORE + +#ifndef TX_DISABLE_STACK_FILLING + + /* Set the thread stack to a pattern prior to creating the initial + stack frame. This pattern is used by the stack checking routines + to see how much has been used. */ + TX_MEMSET(thread_ptr -> tx_thread_stack_start, ((UCHAR) TX_STACK_FILL), thread_ptr -> tx_thread_stack_size); +#endif + + /* Call the target specific stack frame building routine to build the + thread's initial stack and to setup the actual stack pointer in the + control block. */ + _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry); + + /* Disable interrupts. */ + TX_DISABLE + + /* Finally, move into a suspended state to allow for the thread to be resumed. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_RESET_INSERT + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_SUSPENDED) + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status to caller. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_resume.c b/3rd_party/threadx/common/src/tx_thread_resume.c new file mode 100644 index 00000000..57174ded --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_resume.c @@ -0,0 +1,583 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_initialize.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_resume PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes application resume thread services. Actual */ +/* thread resumption is performed in the core service. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to resume */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Resume thread */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_resume(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +TX_THREAD *saved_thread_ptr; +UINT saved_threshold = ((UINT) 0); + +#ifdef TX_INLINE_THREAD_RESUME_SUSPEND +UINT priority; +ULONG priority_bit; +TX_THREAD *head_ptr; +TX_THREAD *tail_ptr; +TX_THREAD *execute_ptr; +TX_THREAD *current_thread; +ULONG combined_flags; + +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif + +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif + + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif +#endif + + /* Lockout interrupts while the thread is being resumed. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_RESUME_INSERT + + /* Determine if the thread is suspended or in the process of suspending. + If so, call the thread resume processing. */ + if (thread_ptr -> tx_thread_state == TX_SUSPENDED) + { + + /* Determine if the create call is being called from initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS) + { + + /* Yes, this resume call was made from initialization. */ + + /* Pickup the current thread execute pointer, which corresponds to the + highest priority thread ready to execute. Interrupt lockout is + not required, since interrupts are assumed to be disabled during + initialization. */ + saved_thread_ptr = _tx_thread_execute_ptr; + + /* Determine if there is thread ready for execution. */ + if (saved_thread_ptr != TX_NULL) + { + + /* Yes, a thread is ready for execution when initialization completes. */ + + /* Save the current preemption-threshold. */ + saved_threshold = saved_thread_ptr -> tx_thread_preempt_threshold; + + /* For initialization, temporarily set the preemption-threshold to the + priority level to make sure the highest-priority thread runs once + initialization is complete. */ + saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority; + } + } + else + { + + /* Simply set the saved thread pointer to NULL. */ + saved_thread_ptr = TX_NULL; + } + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call the actual resume service to resume the thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Determine if the thread's preemption-threshold needs to be restored. */ + if (saved_thread_ptr != TX_NULL) + { + + /* Yes, restore the previous highest-priority thread's preemption-threshold. This + can only happen if this routine is called from initialization. */ + saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold; + } + +#ifdef TX_MISRA_ENABLE + + /* Disable interrupts. */ + TX_DISABLE + + /* Setup successful return status. */ + status = TX_SUCCESS; +#else + + /* Return successful completion. */ + return(TX_SUCCESS); +#endif + + +#else + + /* In-line thread resumption processing follows, which is effectively just taking the + logic in tx_thread_system_resume.c and placing it here! */ + + /* Resume the thread! */ + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&execute_ptr), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time we have + computed the next thread to execute. */ + if (entry_ptr != TX_NULL) + { + + /* Save time stamp. */ + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + + /* Make this thread ready. */ + + /* Change the state to ready. */ + thread_ptr -> tx_thread_state = TX_READY; + + /* Pickup priority of thread. */ + priority = thread_ptr -> tx_thread_priority; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY) + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread resumptions. */ + _tx_thread_performance_resume_count++; + + /* Increment this thread's resume count. */ + thread_ptr -> tx_thread_performance_resume_count++; +#endif + + /* Determine if there are other threads at this priority that are + ready. */ + head_ptr = _tx_thread_priority_list[priority]; + if (head_ptr == TX_NULL) + { + + /* First thread at this priority ready. Add to the front of the list. */ + _tx_thread_priority_list[priority] = thread_ptr; + thread_ptr -> tx_thread_ready_next = thread_ptr; + thread_ptr -> tx_thread_ready_previous = thread_ptr; + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); + + /* Set the active bit to remember that the priority map has something set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_priority_map_active = _tx_thread_priority_map_active | priority_bit; +#endif + + /* Or in the thread's priority bit. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] | priority_bit; + + /* Determine if this newly ready thread is the highest priority. */ + if (priority < _tx_thread_highest_priority) + { + + /* A new highest priority thread is present. */ + + /* Update the highest priority variable. */ + _tx_thread_highest_priority = priority; + + /* Pickup the execute pointer. Since it is going to be referenced multiple + times, it is placed in a local variable. */ + execute_ptr = _tx_thread_execute_ptr; + + /* Determine if no thread is currently executing. */ + if (execute_ptr == TX_NULL) + { + + /* Simply setup the execute pointer. */ + _tx_thread_execute_ptr = thread_ptr; + } + else + { + + /* Another thread has been scheduled for execution. */ + + /* Check to see if this is a higher priority thread and determine if preemption is allowed. */ + if (priority < execute_ptr -> tx_thread_preempt_threshold) + { + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if the preempted thread had preemption-threshold set. */ + if (execute_ptr -> tx_thread_preempt_threshold != execute_ptr -> tx_thread_priority) + { + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = (execute_ptr -> tx_thread_priority)/((UINT) 32); + + /* Set the active bit to remember that the preempt map has something set. */ + TX_DIV32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit; +#endif + + /* Remember that this thread was preempted by a thread above the thread's threshold. */ + TX_MOD32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; + } +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if the caller is an interrupt or from a thread. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Caller is a thread, so this is a solicited preemption. */ + _tx_thread_performance_solicited_preemption_count++; + + /* Increment the thread's solicited preemption counter. */ + execute_ptr -> tx_thread_performance_solicited_preemption_count++; + } + else + { + + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Caller is an interrupt, so this is an interrupt preemption. */ + _tx_thread_performance_interrupt_preemption_count++; + + /* Increment the thread's interrupt preemption counter. */ + execute_ptr -> tx_thread_performance_interrupt_preemption_count++; + } + } + + /* Remember the thread that preempted this thread. */ + execute_ptr -> tx_thread_performance_last_preempting_thread = thread_ptr; +#endif + + /* Yes, modify the execute thread pointer. */ + _tx_thread_execute_ptr = thread_ptr; + +#ifndef TX_MISRA_ENABLE + + /* If MISRA is not-enabled, insert a preemption and return in-line for performance. */ + + /* Determine if the thread's preemption-threshold needs to be restored. */ + if (saved_thread_ptr != TX_NULL) + { + + /* Yes, restore the previous highest-priority thread's preemption-threshold. This + can only happen if this routine is called from initialization. */ + saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold; + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + resume event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to NULL. This can + be used by the trace analysis tool to show idle system conditions. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Now determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* There is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return in-line when MISRA is not enabled. */ + return(TX_SUCCESS); +#endif + } + } + } + } + else + { + + /* No, there are other threads at this priority already ready. */ + + /* Just add this thread to the priority list. */ + tail_ptr = head_ptr -> tx_thread_ready_previous; + tail_ptr -> tx_thread_ready_next = thread_ptr; + head_ptr -> tx_thread_ready_previous = thread_ptr; + thread_ptr -> tx_thread_ready_previous = tail_ptr; + thread_ptr -> tx_thread_ready_next = head_ptr; + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if we should log the execute pointer. */ + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + resume event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to NULL. This can + be used by the trace analysis tool to show idle system conditions. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + + /* Determine if the thread's preemption-threshold needs to be restored. */ + if (saved_thread_ptr != TX_NULL) + { + + /* Yes, restore the previous highest-priority thread's preemption-threshold. This + can only happen if this routine is called from initialization. */ + saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold; + } + + /* Setup successful return status. */ + status = TX_SUCCESS; +#endif + } + else if (thread_ptr -> tx_thread_delayed_suspend == TX_TRUE) + { + + /* Clear the delayed suspension. */ + thread_ptr -> tx_thread_delayed_suspend = TX_FALSE; + + /* Setup delayed suspend lifted return status. */ + status = TX_SUSPEND_LIFTED; + } + else + { + + /* Setup invalid resume return status. */ + status = TX_RESUME_ERROR; + } + + /* Restore interrupts. */ + TX_RESTORE + +#ifdef TX_INLINE_THREAD_RESUME_SUSPEND + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Determine if a preemption condition is present. */ + if (current_thread != _tx_thread_execute_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Now determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* There is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_shell_entry.c b/3rd_party/threadx/common/src/tx_thread_shell_entry.c new file mode 100644 index 00000000..bec5a12d --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_shell_entry.c @@ -0,0 +1,203 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_shell_entry PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, 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 */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* thread_entry Thread's entry function */ +/* _tx_thread_system_suspend Thread suspension routine */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Initial thread stack frame */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_shell_entry(VOID) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type); +#endif + + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_STARTED_EXTENSION(thread_ptr) + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup the entry/exit application callback routine. */ + entry_exit_notify = thread_ptr -> tx_thread_entry_exit_notify; + + /* Restore interrupts. */ + TX_RESTORE + + /* 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_ptr -> tx_thread_entry) (thread_ptr -> tx_thread_entry_parameter); + + /* Suspend thread with a "completed" state. */ + + /* Determine if the application is using mutexes. */ + if (_tx_thread_mutex_release != TX_NULL) + { + + /* Yes, call the mutex release function via a function pointer that + is setup during mutex initialization. */ + (_tx_thread_mutex_release)(thread_ptr); + } + + /* Lockout interrupts while the thread state is setup. */ + TX_DISABLE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the entry/exit application callback routine again. */ + entry_exit_notify = thread_ptr -> tx_thread_entry_exit_notify; +#endif + + /* Set the status to suspending, in order to indicate the suspension + is in progress. */ + thread_ptr -> tx_thread_state = TX_COMPLETED; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_COMPLETED) + +#ifdef TX_NOT_INTERRUPTABLE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* 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 + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_COMPLETED_EXTENSION(thread_ptr) + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup for no timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0); + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_COMPLETED_EXTENSION(thread_ptr) + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* 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. */ + _tx_thread_system_suspend(thread_ptr); +#endif + + +#ifdef TX_SAFETY_CRITICAL + + /* If we ever get here, raise safety critical exception. */ + TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_thread_sleep.c b/3rd_party/threadx/common/src/tx_thread_sleep.c new file mode 100644 index 00000000..c908134c --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_sleep.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_timer.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_sleep PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles application thread sleep requests. If the */ +/* sleep request was called from a non-thread, an error is returned. */ +/* */ +/* INPUT */ +/* */ +/* timer_ticks Number of timer ticks to sleep*/ +/* */ +/* OUTPUT */ +/* */ +/* status Return completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Actual thread suspension */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_sleep(ULONG timer_ticks) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +TX_THREAD *thread_ptr; + + + /* Lockout interrupts while the thread is being resumed. */ + TX_DISABLE + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Determine if this is a legal request. */ + + /* Is there a current thread? */ + if (thread_ptr == TX_NULL) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Illegal caller of this service. */ + status = TX_CALLER_ERROR; + } + + /* Is the caller an ISR or Initialization? */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Illegal caller of this service. */ + status = TX_CALLER_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Is the caller the system timer thread? */ + else if (thread_ptr == &_tx_timer_thread) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Illegal caller of this service. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Determine if the requested number of ticks is zero. */ + else if (timer_ticks == ((ULONG) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Just return with a successful status. */ + status = TX_SUCCESS; + } + else + { + + /* Determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */ + status = TX_CALLER_ERROR; + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SLEEP, TX_ULONG_TO_POINTER_CONVERT(timer_ticks), thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_SLEEP_INSERT + + /* Suspend the current thread. */ + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_SLEEP; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, timer_ticks); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Initialize the status to successful. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + + /* Setup the timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = timer_ticks; + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + + /* Return status to the caller. */ + status = thread_ptr -> tx_thread_suspend_status; + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_stack_analyze.c b/3rd_party/threadx/common/src/tx_thread_stack_analyze.c new file mode 100644 index 00000000..886e4d9e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_stack_analyze.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_analyze PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function analyzes the stack to calculate the highest stack */ +/* pointer in the thread's stack. This can then be used to derive the */ +/* minimum amount of stack left for any given thread. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX internal code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +ULONG *stack_ptr; +ULONG *stack_lowest; +ULONG *stack_highest; +ULONG size; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if the thread pointer is NULL. */ + if (thread_ptr != TX_NULL) + { + + /* Determine if the thread ID is invalid. */ + if (thread_ptr -> tx_thread_id == TX_THREAD_ID) + { + + /* Pickup the current stack variables. */ + stack_lowest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start); + + /* Determine if the pointer is null. */ + if (stack_lowest != TX_NULL) + { + + /* Pickup the highest stack pointer. */ + stack_highest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr); + + /* Determine if the pointer is null. */ + if (stack_highest != TX_NULL) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* We need to binary search the remaining stack for missing 0xEFEFEFEF 32-bit data pattern. + This is a best effort algorithm to find the highest stack usage. */ + do + { + + /* Calculate the size again. */ + size = (ULONG) (TX_ULONG_POINTER_DIF(stack_highest, stack_lowest))/((ULONG) 2); + stack_ptr = TX_ULONG_POINTER_ADD(stack_lowest, size); + + /* Determine if the pattern is still there. */ + if (*stack_ptr != TX_STACK_FILL) + { + + /* Update the stack highest, since we need to look in the upper half now. */ + stack_highest = stack_ptr; + } + else + { + + /* Update the stack lowest, since we need to look in the lower half now. */ + stack_lowest = stack_ptr; + } + + } while(size > ((ULONG) 1)); + + /* Position to first used word - at this point we are within a few words. */ + while (*stack_ptr == TX_STACK_FILL) + { + + /* Position to next word in stack. */ + stack_ptr = TX_ULONG_POINTER_ADD(stack_ptr, 1); + } + + /* Optional processing extension. */ + TX_THREAD_STACK_ANALYZE_EXTENSION + + /* Disable interrupts. */ + TX_DISABLE + + /* Check to see if the thread is still created. */ + if (thread_ptr -> tx_thread_id == TX_THREAD_ID) + { + + /* Yes, thread is still created. */ + + /* Now check the new highest stack pointer is past the stack start. */ + if (stack_ptr > (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_start))) + { + + /* Yes, now check that the new highest stack pointer is less than the previous highest stack pointer. */ + if (stack_ptr < (TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr))) + { + + /* Yes, is the current highest stack pointer pointing at used memory? */ + if (*stack_ptr != TX_STACK_FILL) + { + + /* Yes, setup the highest stack usage. */ + thread_ptr -> tx_thread_stack_highest_ptr = stack_ptr; + } + } + } + } + } + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +} + diff --git a/3rd_party/threadx/common/src/tx_thread_stack_error_handler.c b/3rd_party/threadx/common/src/tx_thread_stack_error_handler.c new file mode 100644 index 00000000..7953bb17 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_stack_error_handler.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#if defined(TX_MISRA_ENABLE) || defined(TX_ENABLE_STACK_CHECKING) +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_error_handler PORTABLE C */ +/* 6.1.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes stack errors detected during run-time. The */ +/* processing currently consists of a spin loop. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX internal code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* update misra support, */ +/* resulting in version 6.1 */ +/* 10-16-2020 William E. Lamie Modified comment(s), */ +/* fixed link issue, */ +/* resulting in version 6.1.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_stack_error_handler(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if the application has registered an error handler. */ + if (_tx_thread_application_stack_error_handler != TX_NULL) + { + + /* Yes, an error handler is present, simply call the application error handler. */ + (_tx_thread_application_stack_error_handler)(thread_ptr); + } + + /* Restore interrupts. */ + TX_RESTORE + +#else + + /* Access input argument just for the sake of lint, MISRA, etc. */ + if (thread_ptr != TX_NULL) + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Restore interrupts. */ + TX_RESTORE + } +#endif +} +#endif /* TX_MISRA_ENABLE */ + diff --git a/3rd_party/threadx/common/src/tx_thread_stack_error_notify.c b/3rd_party/threadx/common/src/tx_thread_stack_error_notify.c new file mode 100644 index 00000000..b4b38924 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_stack_error_notify.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#ifdef TX_ENABLE_STACK_CHECKING +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_error_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers an application stack error handler. If */ +/* ThreadX detects a stack error, this application handler is called. */ +/* */ +/* Note: stack checking must be enabled for this routine to serve any */ +/* purpose via the TX_ENABLE_STACK_CHECKING define. */ +/* */ +/* INPUT */ +/* */ +/* stack_error_handler Pointer to stack error */ +/* handler, TX_NULL to disable */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_stack_error_notify(VOID (*stack_error_handler)(TX_THREAD *thread_ptr)) +{ + +#ifndef TX_ENABLE_STACK_CHECKING + +UINT status; + + + /* Access input argument just for the sake of lint, MISRA, etc. */ + if (stack_error_handler != TX_NULL) + { + + /* Stack checking is not enabled, just return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Stack checking is not enabled, just return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Make entry in event log. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_STACK_ERROR_NOTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Make entry in event log. */ + TX_EL_THREAD_STACK_ERROR_NOTIFY_INSERT + + /* Setup global thread stack error handler. */ + _tx_thread_application_stack_error_handler = stack_error_handler; + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success to caller. */ + return(TX_SUCCESS); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_thread_suspend.c b/3rd_party/threadx/common/src/tx_thread_suspend.c new file mode 100644 index 00000000..956b1e68 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_suspend.c @@ -0,0 +1,849 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +#define TX_SOURCE_CODE + +/* Include necessary system files. */ +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#ifdef TX_INLINE_THREAD_RESUME_SUSPEND +#ifndef TX_NO_TIMER +#include "tx_timer.h" +#endif +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_suspend PORTABLE C */ +/* 6.1.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles application suspend requests. If the suspend */ +/* requires actual processing, this function calls the actual suspend */ +/* thread routine. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* status Return completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_suspend Actual thread suspension */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* 10-16-2020 Yuxin Zhou Modified comment(s), and */ +/* added type cast to address */ +/* a MISRA compliance issue, */ +/* resulting in version 6.1.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_suspend(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *current_thread; +UINT status; + + +#ifndef TX_INLINE_THREAD_RESUME_SUSPEND + + /* Lockout interrupts while the thread is being suspended. */ + TX_DISABLE + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_SUSPEND_INSERT + + /* Check the specified thread's current status. */ + if (thread_ptr -> tx_thread_state == TX_READY) + { + + /* Initialize status to success. */ + status = TX_SUCCESS; + + /* Determine if we are in a thread context. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Yes, we are in a thread context. */ + + /* Determine if the current thread is also the suspending thread. */ + if (current_thread == thread_ptr) + { + + /* Now determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Current thread cannot suspend when the preempt disable flag is non-zero, + return an error. */ + status = TX_SUSPEND_ERROR; + } + } + } + + /* Determine if the status is still successful. */ + if (status == TX_SUCCESS) + { + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup for no timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0); + + /* Temporarily disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + +#ifdef TX_MISRA_ENABLE + + /* Disable interrupts. */ + TX_DISABLE + + /* Return success. */ + status = TX_SUCCESS; +#else + + /* If MISRA is not enabled, return directly. */ + return(TX_SUCCESS); +#endif + } + } + else if (thread_ptr -> tx_thread_state == TX_TERMINATED) + { + + /* Thread is terminated. */ + status = TX_SUSPEND_ERROR; + } + else if (thread_ptr -> tx_thread_state == TX_COMPLETED) + { + + /* Thread is completed. */ + status = TX_SUSPEND_ERROR; + } + else if (thread_ptr -> tx_thread_state == TX_SUSPENDED) + { + + /* Already suspended, just set status to success. */ + status = TX_SUCCESS; + } + else + { + + /* Just set the delayed suspension flag. */ + thread_ptr -> tx_thread_delayed_suspend = TX_TRUE; + + /* Set status to success. */ + status = TX_SUCCESS; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Always return success, since this function does not perform error + checking. */ + return(status); + +#else + + /* In-line thread suspension processing follows, which is effectively just taking the + logic in tx_thread_system_suspend.c and placing it here! */ + +UINT priority; +UINT base_priority; +ULONG priority_map; +ULONG priority_bit; +ULONG combined_flags; +TX_THREAD *ready_next; +TX_THREAD *ready_previous; + +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif + +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif + + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Lockout interrupts while the thread is being suspended. */ + TX_DISABLE + +#ifndef TX_NO_TIMER + + /* Determine if this is the current thread. */ + if (thread_ptr == current_thread) + { + + /* Yes, current thread is suspending - reset time slice for current thread. */ + _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice; + } +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_SUSPEND_INSERT + + /* Check the specified thread's current status. */ + if (thread_ptr -> tx_thread_state == TX_READY) + { + + /* Initialize status to success. */ + status = TX_SUCCESS; + + /* Determine if we are in a thread context. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Yes, we are in a thread context. */ + + /* Determine if the current thread is also the suspending thread. */ + if (current_thread == thread_ptr) + { + + /* Now determine if the preempt disable flag is non-zero. */ + if (_tx_thread_preempt_disable != ((UINT) 0)) + { + + /* Current thread cannot suspend when the preempt disable flag is non-zero, + return an error. */ + status = TX_SUSPEND_ERROR; + } + } + } + + /* Determine if the status is still successful. */ + if (status == TX_SUCCESS) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the thread's suspend count. */ + thread_ptr -> tx_thread_performance_suspend_count++; + + /* Increment the total number of thread suspensions. */ + _tx_thread_performance_suspend_count++; +#endif + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_SUSPENDED) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, ((ULONG) thread_ptr -> tx_thread_state), TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time we have + computed the next thread to execute. */ + if (entry_ptr != TX_NULL) + { + + /* Save time stamp. */ + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + + /* Pickup priority of thread. */ + priority = thread_ptr -> tx_thread_priority; + + /* Pickup the previous and next ready thread pointers. */ + ready_next = thread_ptr -> tx_thread_ready_next; + ready_previous = thread_ptr -> tx_thread_ready_previous; + + /* Determine if there are other threads at this priority that are + ready. */ + if (ready_next != thread_ptr) + { + + /* Yes, there are other threads at this priority ready. */ + + /* Just remove this thread from the priority list. */ + ready_next -> tx_thread_ready_previous = ready_previous; + ready_previous -> tx_thread_ready_next = ready_next; + + /* Determine if this is the head of the priority list. */ + if (_tx_thread_priority_list[priority] == thread_ptr) + { + + /* Update the head pointer of this priority list. */ + _tx_thread_priority_list[priority] = ready_next; + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); +#endif + + /* Check for a thread preempted that had preemption threshold set. */ + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) + { + + /* Ensure that this thread's priority is clear in the preempt map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } +#endif + } + } + else + { + + /* This is the only thread at this priority ready to run. Set the head + pointer to NULL. */ + _tx_thread_priority_list[priority] = TX_NULL; + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); +#endif + + /* Clear this priority bit in the ready priority bit map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this priority map. */ + if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this priority map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_priority_map_active = _tx_thread_priority_map_active & (~(priority_bit)); + } +#endif + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Check for a thread preempted that had preemption-threshold set. */ + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) + { + + /* Ensure that this thread's priority is clear in the preempt map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempted map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } +#endif + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index to find the next highest priority thread ready for execution. */ + priority_map = _tx_thread_priority_map_active; + + /* Determine if there is anything. */ + if (priority_map != ((ULONG) 0)) + { + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) + } + + /* Calculate the base priority as well. */ + base_priority = map_index * ((UINT) 32); +#else + + /* Setup the base priority to zero. */ + base_priority = ((UINT) 0); +#endif + + /* Setup working variable for the priority map. */ + priority_map = _tx_thread_priority_maps[MAP_INDEX]; + + /* Make a quick check for no other threads ready for execution. */ + if (priority_map == ((ULONG) 0)) + { + + /* Nothing else is ready. Set highest priority and execute thread + accordingly. */ + _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES); + _tx_thread_execute_ptr = TX_NULL; + +#ifndef TX_MISRA_ENABLE + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0; + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return to caller. */ + return(TX_SUCCESS); +#endif + } + else + { + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) + + /* Setup the next highest priority variable. */ + _tx_thread_highest_priority = base_priority + priority_bit; + } + } + + /* Determine if this thread is the thread designated to execute. */ + if (thread_ptr == _tx_thread_execute_ptr) + { + + /* Pickup the highest priority thread to execute. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if a previous thread with preemption-threshold was preempted. */ +#if TX_MAX_PRIORITIES > 32 + if (_tx_thread_preempted_map_active != ((ULONG) 0)) +#else + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) +#endif + { + + /* Yes, there was a thread preempted when it was using preemption-threshold. */ + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Interrupts are enabled briefly here to keep the interrupt + lockout time deterministic. */ + + /* Disable interrupts again. */ + TX_DISABLE + + /* Decrement the preemption disable variable. */ + _tx_thread_preempt_disable--; +#endif + + /* Calculate the thread with preemption threshold set that + was interrupted by a thread above the preemption level. */ + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index to find the next highest priority thread ready for execution. */ + priority_map = _tx_thread_preempted_map_active; + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) + + /* Calculate the base priority as well. */ + base_priority = map_index * ((UINT) 32); +#else + + /* Setup the base priority to zero. */ + base_priority = ((UINT) 0); +#endif + + /* Setup temporary preempted map. */ + priority_map = _tx_thread_preempted_maps[MAP_INDEX]; + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) + + /* Setup the highest priority preempted thread. */ + priority = base_priority + priority_bit; + + /* Determine if the next highest priority thread is above the highest priority threshold value. */ + if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold)) + { + + /* Thread not allowed to execute until earlier preempted thread finishes or lowers its + preemption-threshold. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[priority]; + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + + /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } + } +#endif + +#ifndef TX_MISRA_ENABLE + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0; + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return to caller. */ + return(TX_SUCCESS); +#endif + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if a preemption condition is present. */ + if (current_thread != _tx_thread_execute_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if an idle system return is present. */ + if (_tx_thread_execute_ptr == TX_NULL) + { + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; + } + else + { + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; + } +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Return success. */ + status = TX_SUCCESS; + } + } + else if (thread_ptr -> tx_thread_state == TX_TERMINATED) + { + + /* Thread is terminated. */ + status = TX_SUSPEND_ERROR; + } + else if (thread_ptr -> tx_thread_state == TX_COMPLETED) + { + + /* Thread is completed. */ + status = TX_SUSPEND_ERROR; + } + else if (thread_ptr -> tx_thread_state == TX_SUSPENDED) + { + + /* Already suspended, just set status to success. */ + status = TX_SUCCESS; + } + else + { + + /* Just set the delayed suspension flag. */ + thread_ptr -> tx_thread_delayed_suspend = TX_TRUE; + + /* Set status to success. */ + status = TX_SUCCESS; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_thread_system_preempt_check.c b/3rd_party/threadx/common/src/tx_thread_system_preempt_check.c new file mode 100644 index 00000000..9443e4f6 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_system_preempt_check.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_preempt_check PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for preemption that could have occurred as a */ +/* result scheduling activities occurring while the preempt disable */ +/* flag was set. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_return Return to the system */ +/* */ +/* CALLED BY */ +/* */ +/* Other ThreadX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_system_preempt_check(VOID) +{ + +ULONG combined_flags; +TX_THREAD *current_thread; +TX_THREAD *thread_ptr; + + + /* Combine the system state and preempt disable flags into one for comparison. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + + /* Determine if we are in a system state (ISR or Initialization) or internal preemption is disabled. */ + if (combined_flags == ((ULONG) 0)) + { + + /* No, at thread execution level so continue checking for preemption. */ + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Determine if preemption should take place. */ + if (current_thread != thread_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if an idle system return is present. */ + if (thread_ptr == TX_NULL) + { + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; + } + else + { + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; + } +#endif + + /* Return to the system so the higher priority thread can be scheduled. */ + _tx_thread_system_return(); + } + } +} + diff --git a/3rd_party/threadx/common/src/tx_thread_system_resume.c b/3rd_party/threadx/common/src/tx_thread_system_resume.c new file mode 100644 index 00000000..a748e518 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_system_resume.c @@ -0,0 +1,1004 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +/* Include necessary system files. */ +#include "tx_api.h" +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO +#include "tx_initialize.h" +#endif +#include "tx_trace.h" +#include "tx_timer.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_resume PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the specified thread on the list of ready */ +/* threads at the thread's specific priority. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to resume */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_return Return to the system */ +/* _tx_thread_system_ni_resume Noninterruptable thread resume*/ +/* _tx_timer_system_deactivate Timer deactivate */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Thread create function */ +/* _tx_thread_priority_change Thread priority change */ +/* _tx_thread_resume Application resume service */ +/* _tx_thread_timeout Thread timeout */ +/* _tx_thread_wait_abort Thread wait abort */ +/* Other ThreadX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_system_resume(TX_THREAD *thread_ptr) +#ifndef TX_NOT_INTERRUPTABLE +{ + +TX_INTERRUPT_SAVE_AREA + +UINT priority; +ULONG priority_bit; +TX_THREAD *head_ptr; +TX_THREAD *tail_ptr; +TX_THREAD *execute_ptr; +TX_THREAD *current_thread; +ULONG combined_flags; + +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif + +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif + + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Lockout interrupts while the thread is being resumed. */ + TX_DISABLE + +#ifndef TX_NO_TIMER + + /* Deactivate the timeout timer if necessary. */ + if (thread_ptr -> tx_thread_timer.tx_timer_internal_list_head != TX_NULL) + { + + /* Deactivate the thread's timeout timer. */ + _tx_timer_system_deactivate(&(thread_ptr -> tx_thread_timer)); + } + else + { + + /* Clear the remaining time to ensure timer doesn't get activated. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0); + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&execute_ptr), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time we have + computed the next thread to execute. */ + if (entry_ptr != TX_NULL) + { + + /* Save time stamp. */ + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + + /* Decrease the preempt disabled count. */ + _tx_thread_preempt_disable--; + + /* Determine if the thread is in the process of suspending. If so, the thread + control block is already on the linked list so nothing needs to be done. */ + if (thread_ptr -> tx_thread_suspending == TX_FALSE) + { + + /* Thread is not in the process of suspending. Now check to make sure the thread + has not already been resumed. */ + if (thread_ptr -> tx_thread_state != TX_READY) + { + + /* No, now check to see if the delayed suspension flag is set. */ + if (thread_ptr -> tx_thread_delayed_suspend == TX_FALSE) + { + + /* Resume the thread! */ + + /* Make this thread ready. */ + + /* Change the state to ready. */ + thread_ptr -> tx_thread_state = TX_READY; + + /* Pickup priority of thread. */ + priority = thread_ptr -> tx_thread_priority; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY) + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread resumptions. */ + _tx_thread_performance_resume_count++; + + /* Increment this thread's resume count. */ + thread_ptr -> tx_thread_performance_resume_count++; +#endif + + /* Determine if there are other threads at this priority that are + ready. */ + head_ptr = _tx_thread_priority_list[priority]; + if (head_ptr == TX_NULL) + { + + /* First thread at this priority ready. Add to the front of the list. */ + _tx_thread_priority_list[priority] = thread_ptr; + thread_ptr -> tx_thread_ready_next = thread_ptr; + thread_ptr -> tx_thread_ready_previous = thread_ptr; + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); + + /* Set the active bit to remember that the priority map has something set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_priority_map_active = _tx_thread_priority_map_active | priority_bit; +#endif + + /* Or in the thread's priority bit. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] | priority_bit; + + /* Determine if this newly ready thread is the highest priority. */ + if (priority < _tx_thread_highest_priority) + { + + /* A new highest priority thread is present. */ + + /* Update the highest priority variable. */ + _tx_thread_highest_priority = priority; + + /* Pickup the execute pointer. Since it is going to be referenced multiple + times, it is placed in a local variable. */ + execute_ptr = _tx_thread_execute_ptr; + + /* Determine if no thread is currently executing. */ + if (execute_ptr == TX_NULL) + { + + /* Simply setup the execute pointer. */ + _tx_thread_execute_ptr = thread_ptr; + } + else + { + + /* Another thread has been scheduled for execution. */ + + /* Check to see if this is a higher priority thread and determine if preemption is allowed. */ + if (priority < execute_ptr -> tx_thread_preempt_threshold) + { + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if the preempted thread had preemption-threshold set. */ + if (execute_ptr -> tx_thread_preempt_threshold != execute_ptr -> tx_thread_priority) + { + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = (execute_ptr -> tx_thread_priority)/((UINT) 32); + + /* Set the active bit to remember that the preempt map has something set. */ + TX_DIV32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit; +#endif + + /* Remember that this thread was preempted by a thread above the thread's threshold. */ + TX_MOD32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; + } +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if the caller is an interrupt or from a thread. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Caller is a thread, so this is a solicited preemption. */ + _tx_thread_performance_solicited_preemption_count++; + + /* Increment the thread's solicited preemption counter. */ + execute_ptr -> tx_thread_performance_solicited_preemption_count++; + } + else + { + + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Caller is an interrupt, so this is an interrupt preemption. */ + _tx_thread_performance_interrupt_preemption_count++; + + /* Increment the thread's interrupt preemption counter. */ + execute_ptr -> tx_thread_performance_interrupt_preemption_count++; + } + } + + /* Remember the thread that preempted this thread. */ + execute_ptr -> tx_thread_performance_last_preempting_thread = thread_ptr; + +#endif + + /* Yes, modify the execute thread pointer. */ + _tx_thread_execute_ptr = thread_ptr; + +#ifndef TX_MISRA_ENABLE + + /* If MISRA is not-enabled, insert a preemption and return in-line for performance. */ + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + resume event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to NULL. This can + be used by the trace analysis tool to show idle system conditions. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Now determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* There is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return in-line when MISRA is not enabled. */ + return; +#endif + } + } + } + } + else + { + + /* No, there are other threads at this priority already ready. */ + + /* Just add this thread to the priority list. */ + tail_ptr = head_ptr -> tx_thread_ready_previous; + tail_ptr -> tx_thread_ready_next = thread_ptr; + head_ptr -> tx_thread_ready_previous = thread_ptr; + thread_ptr -> tx_thread_ready_previous = tail_ptr; + thread_ptr -> tx_thread_ready_next = head_ptr; + } + } + + /* Else, delayed suspend flag was set. */ + else + { + + /* Clear the delayed suspend flag and change the state. */ + thread_ptr -> tx_thread_delayed_suspend = TX_FALSE; + thread_ptr -> tx_thread_state = TX_SUSPENDED; + } + } + } + else + { + + /* A resumption occurred in the middle of a previous thread suspension. */ + + /* Make sure the type of suspension under way is not a terminate or + thread completion. In either of these cases, do not void the + interrupted suspension processing. */ + if (thread_ptr -> tx_thread_state != TX_COMPLETED) + { + + /* Make sure the thread isn't terminated. */ + if (thread_ptr -> tx_thread_state != TX_TERMINATED) + { + + /* No, now check to see if the delayed suspension flag is set. */ + if (thread_ptr -> tx_thread_delayed_suspend == TX_FALSE) + { + + /* Clear the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + + /* Restore the state to ready. */ + thread_ptr -> tx_thread_state = TX_READY; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY) + } + else + { + + /* Clear the delayed suspend flag and change the state. */ + thread_ptr -> tx_thread_delayed_suspend = TX_FALSE; + thread_ptr -> tx_thread_state = TX_SUSPENDED; + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread resumptions. */ + _tx_thread_performance_resume_count++; + + /* Increment this thread's resume count. */ + thread_ptr -> tx_thread_performance_resume_count++; +#endif + } + } + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + resume event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to NULL. This can + be used by the trace analysis tool to show idle system conditions. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if a preemption condition is present. */ + if (current_thread != _tx_thread_execute_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Now determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* There is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + } +} +#else +{ + +TX_INTERRUPT_SAVE_AREA +#ifdef TX_ENABLE_EVENT_TRACE +UINT temp_state; +#endif +UINT state; + + + /* Lockout interrupts while the thread is being resumed. */ + TX_DISABLE + + /* Decrease the preempt disabled count. */ + _tx_thread_preempt_disable--; + + /* Determine if the thread is in the process of suspending. If so, the thread + control block is already on the linked list so nothing needs to be done. */ + if (thread_ptr -> tx_thread_suspending == TX_FALSE) + { + + /* Call the non-interruptable thread system resume function. */ + _tx_thread_system_ni_resume(thread_ptr); + } + else + { + + /* A resumption occurred in the middle of a previous thread suspension. */ + + /* Pickup the current thread state. */ + state = thread_ptr -> tx_thread_state; + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Move the state into a different variable for MISRA compliance. */ + temp_state = state; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, ((ULONG) state), TX_POINTER_TO_ULONG_CONVERT(&temp_state), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + + /* Make sure the type of suspension under way is not a terminate or + thread completion. In either of these cases, do not void the + interrupted suspension processing. */ + if (state != TX_COMPLETED) + { + + /* Check for terminated thread. */ + if (state != TX_TERMINATED) + { + + /* Clear the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + + /* Restore the state to ready. */ + thread_ptr -> tx_thread_state = TX_READY; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY) + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread resumptions. */ + _tx_thread_performance_resume_count++; + + /* Increment this thread's resume count. */ + thread_ptr -> tx_thread_performance_resume_count++; +#endif + } + } + } + + /* Restore interrupts. */ + TX_RESTORE +} + +/* Define the non-interruptable version of thread resume. It is assumed at this point that + all interrupts are disabled and will remain so during this function. */ + +VOID _tx_thread_system_ni_resume(TX_THREAD *thread_ptr) +{ + +UINT priority; +ULONG priority_bit; +TX_THREAD *head_ptr; +TX_THREAD *tail_ptr; +TX_THREAD *execute_ptr; +TX_THREAD *current_thread; +ULONG combined_flags; + +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif + +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif + + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESUME, thread_ptr, ((ULONG) thread_ptr -> tx_thread_state), TX_POINTER_TO_ULONG_CONVERT(&execute_ptr), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time we have + computed the next thread to execute. */ + if (entry_ptr != TX_NULL) + { + + /* Save time stamp. */ + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + + +#ifndef TX_NO_TIMER + + /* Deactivate the timeout timer if necessary. */ + if (thread_ptr -> tx_thread_timer.tx_timer_internal_list_head != TX_NULL) + { + + /* Deactivate the thread's timeout timer. */ + _tx_timer_system_deactivate(&(thread_ptr -> tx_thread_timer)); + } +#endif + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Thread is not in the process of suspending. Now check to make sure the thread + has not already been resumed. */ + if (thread_ptr -> tx_thread_state != TX_READY) + { + + /* No, now check to see if the delayed suspension flag is set. */ + if (thread_ptr -> tx_thread_delayed_suspend == TX_FALSE) + { + + /* Resume the thread! */ + + /* Make this thread ready. */ + + /* Change the state to ready. */ + thread_ptr -> tx_thread_state = TX_READY; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_READY) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY) + + /* Pickup priority of thread. */ + priority = thread_ptr -> tx_thread_priority; + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread resumptions. */ + _tx_thread_performance_resume_count++; + + /* Increment this thread's resume count. */ + thread_ptr -> tx_thread_performance_resume_count++; +#endif + + /* Determine if there are other threads at this priority that are + ready. */ + head_ptr = _tx_thread_priority_list[priority]; + if (head_ptr == TX_NULL) + { + + /* First thread at this priority ready. Add to the front of the list. */ + _tx_thread_priority_list[priority] = thread_ptr; + thread_ptr -> tx_thread_ready_next = thread_ptr; + thread_ptr -> tx_thread_ready_previous = thread_ptr; + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); + + /* Set the active bit to remember that the priority map has something set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_priority_map_active = _tx_thread_priority_map_active | priority_bit; +#endif + + /* Or in the thread's priority bit. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] | priority_bit; + + /* Determine if this newly ready thread is the highest priority. */ + if (priority < _tx_thread_highest_priority) + { + + /* A new highest priority thread is present. */ + + /* Update the highest priority variable. */ + _tx_thread_highest_priority = priority; + + /* Pickup the execute pointer. Since it is going to be referenced multiple + times, it is placed in a local variable. */ + execute_ptr = _tx_thread_execute_ptr; + + /* Determine if no thread is currently executing. */ + if (execute_ptr == TX_NULL) + { + + /* Simply setup the execute pointer. */ + _tx_thread_execute_ptr = thread_ptr; + } + else + { + + /* Check to see if this is a higher priority thread and determine if preemption is allowed. */ + if (priority < execute_ptr -> tx_thread_preempt_threshold) + { + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if the preempted thread had preemption-threshold set. */ + if (execute_ptr -> tx_thread_preempt_threshold != execute_ptr -> tx_thread_priority) + { + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = (execute_ptr -> tx_thread_priority)/((UINT) 32); + + /* Set the active bit to remember that the preempt map has something set. */ + TX_DIV32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit; +#endif + + /* Remember that this thread was preempted by a thread above the thread's threshold. */ + TX_MOD32_BIT_SET(execute_ptr -> tx_thread_priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit; + } +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if the caller is an interrupt or from a thread. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Caller is a thread, so this is a solicited preemption. */ + _tx_thread_performance_solicited_preemption_count++; + + /* Increment the thread's solicited preemption counter. */ + execute_ptr -> tx_thread_performance_solicited_preemption_count++; + } + else + { + + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Caller is an interrupt, so this is an interrupt preemption. */ + _tx_thread_performance_interrupt_preemption_count++; + + /* Increment the thread's interrupt preemption counter. */ + execute_ptr -> tx_thread_performance_interrupt_preemption_count++; + } + } + + /* Remember the thread that preempted this thread. */ + execute_ptr -> tx_thread_performance_last_preempting_thread = thread_ptr; +#endif + + /* Yes, modify the execute thread pointer. */ + _tx_thread_execute_ptr = thread_ptr; + +#ifndef TX_MISRA_ENABLE + + /* If MISRA is not-enabled, insert a preemption and return in-line for performance. */ + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + resume event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to NULL. This can + be used by the trace analysis tool to show idle system conditions. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); + } + } +#endif + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Now determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* There is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return in-line when MISRA is not enabled. */ + return; +#endif + } + } + } + } + else + { + + /* No, there are other threads at this priority already ready. */ + + /* Just add this thread to the priority list. */ + tail_ptr = head_ptr -> tx_thread_ready_previous; + tail_ptr -> tx_thread_ready_next = thread_ptr; + head_ptr -> tx_thread_ready_previous = thread_ptr; + thread_ptr -> tx_thread_ready_previous = tail_ptr; + thread_ptr -> tx_thread_ready_next = head_ptr; + } + } + + /* Else, delayed suspend flag was set. */ + else + { + + /* Clear the delayed suspend flag and change the state. */ + thread_ptr -> tx_thread_delayed_suspend = TX_FALSE; + thread_ptr -> tx_thread_state = TX_SUSPENDED; + } + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + resume event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Does the timestamp match? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to NULL. This can + be used by the trace analysis tool to show idle system conditions. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Determine if a preemption condition is present. */ + if (current_thread != _tx_thread_execute_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Now determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* There is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + } +} +#endif diff --git a/3rd_party/threadx/common/src/tx_thread_system_suspend.c b/3rd_party/threadx/common/src/tx_thread_system_suspend.c new file mode 100644 index 00000000..ee3c1edb --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_system_suspend.c @@ -0,0 +1,1220 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_suspend PORTABLE C */ +/* 6.1 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function suspends the specified thread and changes the thread */ +/* state to the value specified. Note: delayed suspension processing */ +/* is handled outside of this routine. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_return Return to system */ +/* _tx_thread_system_preempt_check System preemption check */ +/* _tx_timer_system_activate Activate timer for timeout */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_priority_change Thread priority change */ +/* _tx_thread_shell_entry Thread shell function */ +/* _tx_thread_sleep Thread sleep */ +/* _tx_thread_suspend Application thread suspend */ +/* _tx_thread_terminate Thread terminate */ +/* Other ThreadX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_system_suspend(TX_THREAD *thread_ptr) +#ifndef TX_NOT_INTERRUPTABLE +{ + +TX_INTERRUPT_SAVE_AREA + +UINT priority; +UINT base_priority; +ULONG priority_map; +ULONG priority_bit; +ULONG combined_flags; +TX_THREAD *ready_next; +TX_THREAD *ready_previous; +TX_THREAD *current_thread; + +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif + +#ifndef TX_NO_TIMER +ULONG timeout; +#endif + +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Lockout interrupts while the thread is being suspended. */ + TX_DISABLE + +#ifndef TX_NO_TIMER + + /* Is the current thread suspending? */ + if (thread_ptr == current_thread) + { + + /* Pickup the wait option. */ + timeout = thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks; + + /* Determine if an activation is needed. */ + if (timeout != TX_NO_WAIT) + { + + /* Make sure the suspension is not a wait-forever. */ + if (timeout != TX_WAIT_FOREVER) + { + + /* Activate the thread timer with the timeout value setup in the caller. */ + _tx_timer_system_activate(&(thread_ptr -> tx_thread_timer)); + } + } + + /* Yes, reset time slice for current thread. */ + _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice; + } +#endif + + /* Decrease the preempt disabled count. */ + _tx_thread_preempt_disable--; + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the thread's suspend count. */ + thread_ptr -> tx_thread_performance_suspend_count++; + + /* Increment the total number of thread suspensions. */ + _tx_thread_performance_suspend_count++; +#endif + + /* Check to make sure the thread suspending flag is still set. If not, it + has already been resumed. */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, thread_ptr -> tx_thread_state) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time we have + computed the next thread to execute. */ + if (entry_ptr != TX_NULL) + { + + /* Save time stamp. */ + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + + /* Actually suspend this thread. But first, clear the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + + /* Pickup priority of thread. */ + priority = thread_ptr -> tx_thread_priority; + + /* Pickup the next ready thread pointer. */ + ready_next = thread_ptr -> tx_thread_ready_next; + + /* Determine if there are other threads at this priority that are + ready. */ + if (ready_next != thread_ptr) + { + + /* Yes, there are other threads at this priority ready. */ + + /* Pickup the previous ready thread pointer. */ + ready_previous = thread_ptr -> tx_thread_ready_previous; + + /* Just remove this thread from the priority list. */ + ready_next -> tx_thread_ready_previous = ready_previous; + ready_previous -> tx_thread_ready_next = ready_next; + + /* Determine if this is the head of the priority list. */ + if (_tx_thread_priority_list[priority] == thread_ptr) + { + + /* Update the head pointer of this priority list. */ + _tx_thread_priority_list[priority] = ready_next; + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); +#endif + + /* Check for a thread preempted that had preemption threshold set. */ + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) + { + + /* Ensure that this thread's priority is clear in the preempt map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } +#endif + } + } + else + { + + /* This is the only thread at this priority ready to run. Set the head + pointer to NULL. */ + _tx_thread_priority_list[priority] = TX_NULL; + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); +#endif + + /* Clear this priority bit in the ready priority bit map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this priority map. */ + if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this priority map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_priority_map_active = _tx_thread_priority_map_active & (~(priority_bit)); + } +#endif + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Check for a thread preempted that had preemption-threshold set. */ + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) + { + + /* Ensure that this thread's priority is clear in the preempt map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempted map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } +#endif + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index to find the next highest priority thread ready for execution. */ + priority_map = _tx_thread_priority_map_active; + + /* Determine if there is anything. */ + if (priority_map != ((ULONG) 0)) + { + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) + } + + /* Calculate the base priority as well. */ + base_priority = map_index * ((UINT) 32); +#else + + /* Setup the base priority to zero. */ + base_priority = ((UINT) 0); +#endif + + /* Setup working variable for the priority map. */ + priority_map = _tx_thread_priority_maps[MAP_INDEX]; + + /* Make a quick check for no other threads ready for execution. */ + if (priority_map == ((ULONG) 0)) + { + + /* Nothing else is ready. Set highest priority and execute thread + accordingly. */ + _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES); + _tx_thread_execute_ptr = TX_NULL; + +#ifndef TX_MISRA_ENABLE + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0; + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return to caller. */ + return; +#endif + } + else + { + + /* Other threads at different priority levels are ready to run. */ + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) + + /* Setup the next highest priority variable. */ + _tx_thread_highest_priority = base_priority + ((UINT) priority_bit); + } + } + + /* Determine if the suspending thread is the thread designated to execute. */ + if (thread_ptr == _tx_thread_execute_ptr) + { + + /* Pickup the highest priority thread to execute. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if a previous thread with preemption-threshold was preempted. */ +#if TX_MAX_PRIORITIES > 32 + if (_tx_thread_preempted_map_active != ((ULONG) 0)) +#else + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) +#endif + { + + /* Yes, there was a thread preempted when it was using preemption-threshold. */ + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Interrupts are enabled briefly here to keep the interrupt + lockout time deterministic. */ + + /* Disable interrupts again. */ + TX_DISABLE + + /* Decrement the preemption disable variable. */ + _tx_thread_preempt_disable--; + + /* Calculate the thread with preemption threshold set that + was interrupted by a thread above the preemption level. */ + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index to find the next highest priority thread ready for execution. */ + priority_map = _tx_thread_preempted_map_active; + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) + + /* Calculate the base priority as well. */ + base_priority = map_index * ((UINT) 32); +#else + + /* Setup the base priority to zero. */ + base_priority = ((UINT) 0); +#endif + + /* Setup temporary preempted map. */ + priority_map = _tx_thread_preempted_maps[MAP_INDEX]; + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) + + /* Setup the highest priority preempted thread. */ + priority = base_priority + ((UINT) priority_bit); + + /* Determine if the next highest priority thread is above the highest priority threshold value. */ + if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold)) + { + + /* Thread not allowed to execute until earlier preempted thread finishes or lowers its + preemption-threshold. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[priority]; + + /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } + } +#endif + +#ifndef TX_MISRA_ENABLE + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); + } + } +#endif + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return to caller. */ + return; +#endif + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Determine if a preemption condition is present. */ + if (current_thread != _tx_thread_execute_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if an idle system return is present. */ + if (_tx_thread_execute_ptr == TX_NULL) + { + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; + } + else + { + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; + } +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + } + + /* Return to caller. */ + return; +} +#else +/* Define the entry function for modules assuming the interruptable version of system suspend. */ +{ + +TX_INTERRUPT_SAVE_AREA + +ULONG wait_option; + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if the thread is still suspending. */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + + /* Yes, prepare to call the non-interruptable system suspend function. */ + + /* Clear the thread suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + + /* Pickup the wait option. */ + wait_option = thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks; + + /* Decrement the preempt disable count. */ + _tx_thread_preempt_disable--; + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, wait_option); + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); +} + +/* Define the system suspend function that is not interruptable, i.e., it is assumed that + interrupts are disabled upon calling this function. */ + +VOID _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option) +{ + +UINT priority; +UINT base_priority; +ULONG priority_map; +ULONG priority_bit; +ULONG combined_flags; +TX_THREAD *ready_next; +TX_THREAD *ready_previous; +TX_THREAD *current_thread; + +#if TX_MAX_PRIORITIES > 32 +UINT map_index; +#endif + +#ifdef TX_ENABLE_EVENT_TRACE +TX_TRACE_BUFFER_ENTRY *entry_ptr; +ULONG time_stamp = ((ULONG) 0); +#endif + + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + +#ifndef TX_NO_TIMER + + + /* Determine if a timeout needs to be activated. */ + if (thread_ptr == current_thread) + { + + /* Is there a wait option? */ + if (wait_option != TX_NO_WAIT) + { + + /* Make sure it is not a wait-forever option. */ + if (wait_option != TX_WAIT_FOREVER) + { + + /* Setup the wait option. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option; + + /* Activate the thread timer with the timeout value setup in the caller. */ + _tx_timer_system_activate(&(thread_ptr -> tx_thread_timer)); + } + } + + /* Reset time slice for current thread. */ + _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice; + } +#endif + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the thread's suspend count. */ + thread_ptr -> tx_thread_performance_suspend_count++; + + /* Increment the total number of thread suspensions. */ + _tx_thread_performance_suspend_count++; +#endif + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, thread_ptr -> tx_thread_state) + + /* Log the thread status change. */ + TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, thread_ptr -> tx_thread_state) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, save the current event pointer. */ + entry_ptr = _tx_trace_buffer_current_ptr; +#endif + + /* Log the thread status change. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&priority), TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), TX_TRACE_INTERNAL_EVENTS) + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Save the time stamp for later comparison to verify that + the event hasn't been overwritten by the time we have + computed the next thread to execute. */ + if (entry_ptr != TX_NULL) + { + + /* Save time stamp. */ + time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp; + } +#endif + + /* Pickup priority of thread. */ + priority = thread_ptr -> tx_thread_priority; + + /* Pickup the next ready thread pointer. */ + ready_next = thread_ptr -> tx_thread_ready_next; + + /* Determine if there are other threads at this priority that are + ready. */ + if (ready_next != thread_ptr) + { + + /* Yes, there are other threads at this priority ready. */ + + /* Pickup the previous ready thread pointer. */ + ready_previous = thread_ptr -> tx_thread_ready_previous; + + /* Just remove this thread from the priority list. */ + ready_next -> tx_thread_ready_previous = ready_previous; + ready_previous -> tx_thread_ready_next = ready_next; + + /* Determine if this is the head of the priority list. */ + if (_tx_thread_priority_list[priority] == thread_ptr) + { + + /* Update the head pointer of this priority list. */ + _tx_thread_priority_list[priority] = ready_next; + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); +#endif + + /* Check for a thread preempted that had preemption threshold set. */ + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) + { + + /* Ensure that this thread's priority is clear in the preempt map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } +#endif + } + } + else + { + + /* This is the only thread at this priority ready to run. Set the head + pointer to NULL. */ + _tx_thread_priority_list[priority] = TX_NULL; + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index into the bit map array. */ + map_index = priority/((UINT) 32); +#endif + + /* Clear this priority bit in the ready priority bit map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_priority_maps[MAP_INDEX] = _tx_thread_priority_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this priority map. */ + if (_tx_thread_priority_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this priority map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_priority_map_active = _tx_thread_priority_map_active & (~(priority_bit)); + } +#endif + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Check for a thread preempted that had preemption-threshold set. */ + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) + { + + /* Ensure that this thread's priority is clear in the preempt map. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempted map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } +#endif + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index to find the next highest priority thread ready for execution. */ + priority_map = _tx_thread_priority_map_active; + + /* Determine if there is anything. */ + if (priority_map != ((ULONG) 0)) + { + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) + } + + /* Calculate the base priority as well. */ + base_priority = map_index * ((UINT) 32); +#else + + /* Setup the base priority to zero. */ + base_priority = ((UINT) 0); +#endif + + /* Setup working variable for the priority map. */ + priority_map = _tx_thread_priority_maps[MAP_INDEX]; + + /* Make a quick check for no other threads ready for execution. */ + if (priority_map == ((ULONG) 0)) + { + + /* Nothing else is ready. Set highest priority and execute thread + accordingly. */ + _tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES); + _tx_thread_execute_ptr = TX_NULL; + +#ifndef TX_MISRA_ENABLE + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = 0; + } + } +#endif + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return to caller. */ + return; +#endif + } + else + { + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) + + /* Setup the next highest priority variable. */ + _tx_thread_highest_priority = base_priority + ((UINT) priority_bit); + } + } + + /* Determine if the suspending thread is the thread designated to execute. */ + if (thread_ptr == _tx_thread_execute_ptr) + { + + /* Pickup the highest priority thread to execute. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; + +#ifndef TX_DISABLE_PREEMPTION_THRESHOLD + + /* Determine if a previous thread with preemption-threshold was preempted. */ +#if TX_MAX_PRIORITIES > 32 + if (_tx_thread_preempted_map_active != ((ULONG) 0)) +#else + if (_tx_thread_preempted_maps[MAP_INDEX] != ((ULONG) 0)) +#endif + { + + /* Yes, there was a thread preempted when it was using preemption-threshold. */ + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Decrement the preemption disable variable. */ + _tx_thread_preempt_disable--; + + /* Calculate the thread with preemption threshold set that + was interrupted by a thread above the preemption level. */ + +#if TX_MAX_PRIORITIES > 32 + + /* Calculate the index to find the next highest priority thread ready for execution. */ + priority_map = _tx_thread_preempted_map_active; + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, map_index) + + /* Calculate the base priority as well. */ + base_priority = map_index * ((UINT) 32); +#else + + /* Setup the base priority to zero. */ + base_priority = ((UINT) 0); +#endif + + /* Setup temporary preempted map. */ + priority_map = _tx_thread_preempted_maps[MAP_INDEX]; + + /* Calculate the lowest bit set in the priority map. */ + TX_LOWEST_SET_BIT_CALCULATE(priority_map, priority_bit) + + /* Setup the highest priority preempted thread. */ + priority = base_priority + ((UINT) priority_bit); + + /* Determine if the next highest priority thread is above the highest priority threshold value. */ + if (_tx_thread_highest_priority >= (_tx_thread_priority_list[priority] -> tx_thread_preempt_threshold)) + { + + /* Thread not allowed to execute until earlier preempted thread finishes or lowers its + preemption-threshold. */ + _tx_thread_execute_ptr = _tx_thread_priority_list[priority]; + + /* Clear the corresponding bit in the preempted map, since the preemption has been restored. */ + TX_MOD32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit)); + +#if TX_MAX_PRIORITIES > 32 + + /* Determine if there are any other bits set in this preempt map. */ + if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0)) + { + + /* No, clear the active bit to signify this preempt map has nothing set. */ + TX_DIV32_BIT_SET(priority, priority_bit) + _tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit)); + } +#endif + } + } +#endif + +#ifndef TX_MISRA_ENABLE + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); + } + } +#endif + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + + /* Return to caller. */ + return; +#endif + } + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Is the execute pointer different? */ + if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr) + { + + /* Move to next entry. */ + _tx_thread_performance__execute_log_index++; + + /* Check for wrap condition. */ + if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE) + { + + /* Set the index to the beginning. */ + _tx_thread_performance__execute_log_index = ((UINT) 0); + } + + /* Log the new execute pointer. */ + _tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr; + } +#endif + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Check that the event time stamp is unchanged. A different + timestamp means that a later event wrote over the thread + suspend event. In that case, do nothing here. */ + if (entry_ptr != TX_NULL) + { + + /* Is the timestamp the same? */ + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + + /* Timestamp is the same, set the "next thread pointer" to the new value of the + next thread to execute. This can be used by the trace analysis tool to keep + track of next thread execution. */ +#ifdef TX_MISRA_ENABLE + entry_ptr -> tx_trace_buffer_entry_info_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#else + entry_ptr -> tx_trace_buffer_entry_information_field_4 = TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr); +#endif + } + } +#endif + + /* Determine if a preemption condition is present. */ + if (current_thread != _tx_thread_execute_ptr) + { + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + thread_ptr = _tx_thread_execute_ptr; + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) +#endif + + /* Determine if preemption should take place. This is only possible if the current thread pointer is + not the same as the execute thread pointer AND the system state and preempt disable flags are clear. */ + TX_THREAD_SYSTEM_RETURN_CHECK(combined_flags) + if (combined_flags == ((ULONG) 0)) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Determine if an idle system return is present. */ + if (_tx_thread_execute_ptr == TX_NULL) + { + + /* Yes, increment the return to idle return count. */ + _tx_thread_performance_idle_return_count++; + } + else + { + + /* No, there is another thread ready to run and will be scheduled upon return. */ + _tx_thread_performance_non_idle_return_count++; + } +#endif + + /* Preemption is needed - return to the system! */ + _tx_thread_system_return(); + } + } + + /* Return to caller. */ + return; +} +#endif + diff --git a/3rd_party/threadx/common/src/tx_thread_terminate.c b/3rd_party/threadx/common/src/tx_thread_terminate.c new file mode 100644 index 00000000..f84a4994 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_terminate.c @@ -0,0 +1,312 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_terminate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles application thread terminate requests. Once */ +/* a thread is terminated, it cannot be executed again unless it is */ +/* deleted and recreated. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* status Return completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_system_deactivate Timer deactivate function */ +/* _tx_thread_system_suspend Actual thread suspension */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend */ +/* thread */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* Suspend Cleanup Routine Suspension cleanup function */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_terminate(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +VOID (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence); +#ifndef TX_DISABLE_NOTIFY_CALLBACKS +VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id); +#endif +UINT status; +ULONG suspension_sequence; + + + /* Default to successful completion. */ + status = TX_SUCCESS; + + /* Lockout interrupts while the thread is being terminated. */ + TX_DISABLE + + /* Deactivate thread timer, if active. */ + _tx_timer_system_deactivate(&thread_ptr -> tx_thread_timer); + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TERMINATE, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&suspend_cleanup), 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_TERMINATE_INSERT + + /* Is the thread already terminated? */ + if (thread_ptr -> tx_thread_state == TX_TERMINATED) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Return success since thread is already terminated. */ + status = TX_SUCCESS; + } + + /* Check the specified thread's current status. */ + else if (thread_ptr -> tx_thread_state != TX_COMPLETED) + { + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the entry/exit application callback routine. */ + entry_exit_notify = thread_ptr -> tx_thread_entry_exit_notify; +#endif + + /* Check to see if the thread is currently ready. */ + if (thread_ptr -> tx_thread_state == TX_READY) + { + + /* Set the state to terminated. */ + thread_ptr -> tx_thread_state = TX_TERMINATED; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED) + +#ifdef TX_NOT_INTERRUPTABLE + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* 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 non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Setup for no timeout period. */ + thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0); + + /* Disable preemption. */ + _tx_thread_preempt_disable++; + + /* Since the thread is currently ready, we don't need to + worry about calling the suspend cleanup routine! */ + + /* Restore interrupts. */ + TX_RESTORE + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* 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. */ + _tx_thread_system_suspend(thread_ptr); + + /* Disable interrupts. */ + TX_DISABLE +#endif + } + else + { + + /* Change the state to terminated. */ + thread_ptr -> tx_thread_state = TX_TERMINATED; + + /* Thread state change. */ + TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED) + + /* Set the suspending flag. This prevents the thread from being + resumed before the cleanup routine is executed. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Pickup the cleanup routine address. */ + suspend_cleanup = thread_ptr -> tx_thread_suspend_cleanup; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Pickup the suspension sequence number that is used later to verify that the + cleanup is still necessary. */ + suspension_sequence = thread_ptr -> tx_thread_suspension_sequence; +#else + + /* When not interruptable is selected, the suspension sequence is not used - just set to 0. */ + suspension_sequence = ((ULONG) 0); +#endif + +#ifndef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Call any cleanup routines. */ + if (suspend_cleanup != TX_NULL) + { + + /* Yes, there is a function to call. */ + (suspend_cleanup)(thread_ptr, suspension_sequence); + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts. */ + TX_DISABLE +#endif + + /* Clear the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Perform any additional activities for tool or user purpose. */ + TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* 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 + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts. */ + TX_DISABLE +#endif + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Determine if the application is using mutexes. */ + if (_tx_thread_mutex_release != TX_NULL) + { + + /* Yes, call the mutex release function via a function pointer that + is setup during initialization. */ + (_tx_thread_mutex_release)(thread_ptr); + } + +#ifndef TX_NOT_INTERRUPTABLE + + /* Disable interrupts. */ + TX_DISABLE +#endif + + /* Enable preemption. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_time_slice.c b/3rd_party/threadx/common/src/tx_thread_time_slice.c new file mode 100644 index 00000000..4dac5545 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_time_slice.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#ifndef TX_NO_TIMER + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_time_slice PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function moves the currently executing thread to the end of */ +/* the threads ready at the same priority level as a result of a */ +/* time-slice interrupt. If no other thread of the same priority is */ +/* ready, this function simply returns. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_timer_interrupt Timer interrupt handling */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Scott Larson Modified comment(s), and */ +/* opt out of function when */ +/* TX_NO_TIMER is defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_time_slice(VOID) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +#ifdef TX_ENABLE_STACK_CHECKING +TX_THREAD *next_thread_ptr; +#endif +#ifdef TX_ENABLE_EVENT_TRACE +ULONG system_state; +UINT preempt_disable; +#endif + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Check this thread's stack. */ + TX_THREAD_STACK_CHECK(thread_ptr) + + /* Set the next thread pointer to NULL. */ + next_thread_ptr = TX_NULL; +#endif + + /* Lockout interrupts while the time-slice is evaluated. */ + TX_DISABLE + + /* Clear the expired time-slice flag. */ + _tx_timer_expired_time_slice = TX_FALSE; + + /* Make sure the thread pointer is valid. */ + if (thread_ptr != TX_NULL) + { + + /* Make sure the thread is still active, i.e. not suspended. */ + if (thread_ptr -> tx_thread_state == TX_READY) + { + + /* Setup a fresh time-slice for the thread. */ + thread_ptr -> tx_thread_time_slice = thread_ptr -> tx_thread_new_time_slice; + + /* Reset the actual time-slice variable. */ + _tx_timer_time_slice = thread_ptr -> tx_thread_time_slice; + + /* Determine if there is another thread at the same priority and preemption-threshold + is not set. Preemption-threshold overrides time-slicing. */ + if (thread_ptr -> tx_thread_ready_next != thread_ptr) + { + + /* Check to see if preemption-threshold is not being used. */ + if (thread_ptr -> tx_thread_priority == thread_ptr -> tx_thread_preempt_threshold) + { + + /* Preemption-threshold is not being used by this thread. */ + + /* There is another thread at this priority, make it the highest at + this priority level. */ + _tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr -> tx_thread_ready_next; + + /* Designate the highest priority thread as the one to execute. Don't use this + thread's priority as an index just in case a higher priority thread is now + ready! */ + _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority]; + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the thread's time-slice counter. */ + thread_ptr -> tx_thread_performance_time_slice_count++; + + /* Increment the total number of thread time-slice operations. */ + _tx_thread_performance_time_slice_count++; +#endif + + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Pickup the next execute pointer. */ + next_thread_ptr = _tx_thread_execute_ptr; +#endif + } + } + } + } + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Pickup the volatile information. */ + system_state = TX_THREAD_GET_SYSTEM_STATE(); + preempt_disable = _tx_thread_preempt_disable; + + /* Insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SLICE, _tx_thread_execute_ptr, system_state, preempt_disable, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_INTERNAL_EVENTS) +#endif + + /* Restore previous interrupt posture. */ + TX_RESTORE + +#ifdef TX_ENABLE_STACK_CHECKING + + /* Determine if there is a next thread pointer to perform stack checking on. */ + if (next_thread_ptr != TX_NULL) + { + + /* Yes, check this thread's stack. */ + TX_THREAD_STACK_CHECK(next_thread_ptr) + } +#endif +} + +#endif diff --git a/3rd_party/threadx/common/src/tx_thread_time_slice_change.c b/3rd_party/threadx/common/src/tx_thread_time_slice_change.c new file mode 100644 index 00000000..23e1eff9 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_time_slice_change.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_time_slice_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes thread time slice change requests. The */ +/* previous time slice is returned to the caller. If the new request */ +/* is made for an executing thread, it is also placed in the actual */ +/* time-slice countdown variable. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread */ +/* new_time_slice New time slice */ +/* old_time_slice Old time slice */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *current_thread; + + + /* Lockout interrupts while the thread is being resumed. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TIME_SLICE_CHANGE, thread_ptr, new_time_slice, thread_ptr -> tx_thread_new_time_slice, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_TIME_SLICE_CHANGE_INSERT + + /* Return the old time slice. */ + *old_time_slice = thread_ptr -> tx_thread_new_time_slice; + + /* Setup the new time-slice. */ + thread_ptr -> tx_thread_time_slice = new_time_slice; + thread_ptr -> tx_thread_new_time_slice = new_time_slice; + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Determine if this thread is the currently executing thread. */ + if (thread_ptr == current_thread) + { + + /* Yes, update the time-slice countdown variable. */ + _tx_timer_time_slice = new_time_slice; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_thread_timeout.c b/3rd_party/threadx/common/src/tx_thread_timeout.c new file mode 100644 index 00000000..82f51d61 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_timeout.c @@ -0,0 +1,166 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_timeout PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles thread timeout processing. Timeouts occur in */ +/* two flavors, namely the thread sleep timeout and all other service */ +/* call timeouts. Thread sleep timeouts are processed locally, while */ +/* the others are processed by the appropriate suspension clean-up */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* timeout_input Contains the thread pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* Suspension Cleanup Functions */ +/* _tx_thread_system_resume Resume thread */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_timer_expiration_process Timer expiration function */ +/* _tx_timer_thread_entry Timer thread function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_timeout(ULONG timeout_input) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +VOID (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence); +ULONG suspension_sequence; + + + /* Pickup the thread pointer. */ + TX_THREAD_TIMEOUT_POINTER_SETUP(thread_ptr) + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine how the thread is currently suspended. */ + if (thread_ptr -> tx_thread_state == TX_SLEEP) + { + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Increment the disable preemption flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Lift the suspension on the sleeping thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + } + else + { + + /* Process all other suspension timeouts. */ + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread timeouts. */ + _tx_thread_performance_timeout_count++; + + /* Increment the number of timeouts for this thread. */ + thread_ptr -> tx_thread_performance_timeout_count++; +#endif + + /* Pickup the cleanup routine address. */ + suspend_cleanup = thread_ptr -> tx_thread_suspend_cleanup; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Pickup the suspension sequence number that is used later to verify that the + cleanup is still necessary. */ + suspension_sequence = thread_ptr -> tx_thread_suspension_sequence; +#else + + /* When not interruptable is selected, the suspension sequence is not used - just set to 0. */ + suspension_sequence = ((ULONG) 0); +#endif + +#ifndef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Call any cleanup routines. */ + if (suspend_cleanup != TX_NULL) + { + /* Yes, there is a function to call. */ + (suspend_cleanup)(thread_ptr, suspension_sequence); + } + +#ifdef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE +#endif + } +} + diff --git a/3rd_party/threadx/common/src/tx_thread_wait_abort.c b/3rd_party/threadx/common/src/tx_thread_wait_abort.c new file mode 100644 index 00000000..e5fbffae --- /dev/null +++ b/3rd_party/threadx/common/src/tx_thread_wait_abort.c @@ -0,0 +1,237 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_wait_abort PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function aborts the wait condition that the specified thread */ +/* is in - regardless of what object the thread is waiting on - and */ +/* returns a TX_WAIT_ABORTED status to the specified thread. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread to abort the wait on */ +/* */ +/* OUTPUT */ +/* */ +/* status Return completion status */ +/* */ +/* CALLS */ +/* */ +/* Suspension Cleanup Functions */ +/* _tx_thread_system_resume */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_thread_wait_abort(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +VOID (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence); +UINT status; +ULONG suspension_sequence; + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_WAIT_ABORT, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS) + + /* Log this kernel call. */ + TX_EL_THREAD_WAIT_ABORT_INSERT + + /* Determine if the thread is currently suspended. */ + if (thread_ptr -> tx_thread_state < TX_SLEEP) + { + + /* Thread is either ready, completed, terminated, or in a pure + suspension condition. */ + + /* Restore interrupts. */ + TX_RESTORE + + /* Just return with an error message to indicate that + nothing was done. */ + status = TX_WAIT_ABORT_ERROR; + } + else + { + + /* Check for a sleep condition. */ + if (thread_ptr -> tx_thread_state == TX_SLEEP) + { + + /* Set the state to terminated. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + + /* Set the TX_WAIT_ABORTED status in the thread that is + sleeping. */ + thread_ptr -> tx_thread_suspend_status = TX_WAIT_ABORTED; + + /* Make sure there isn't a suspend cleanup routine. */ + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the disable preemption flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE +#endif + } + else + { + + /* Process all other suspension timeouts. */ + + /* Set the state to suspended. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + + /* Pickup the cleanup routine address. */ + suspend_cleanup = thread_ptr -> tx_thread_suspend_cleanup; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Pickup the suspension sequence number that is used later to verify that the + cleanup is still necessary. */ + suspension_sequence = thread_ptr -> tx_thread_suspension_sequence; +#else + + /* When not interruptable is selected, the suspension sequence is not used - just set to 0. */ + suspension_sequence = ((ULONG) 0); +#endif + + /* Set the TX_WAIT_ABORTED status in the thread that was + suspended. */ + thread_ptr -> tx_thread_suspend_status = TX_WAIT_ABORTED; + +#ifndef TX_NOT_INTERRUPTABLE + + /* Increment the disable preemption flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Call any cleanup routines. */ + if (suspend_cleanup != TX_NULL) + { + + /* Yes, there is a function to call. */ + (suspend_cleanup)(thread_ptr, suspension_sequence); + } + } + + /* If the abort of the thread wait was successful, if so resume the thread. */ + if (thread_ptr -> tx_thread_suspend_status == TX_WAIT_ABORTED) + { + +#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO + + /* Increment the total number of thread wait aborts. */ + _tx_thread_performance_wait_abort_count++; + + /* Increment this thread's wait abort count. */ + thread_ptr -> tx_thread_performance_wait_abort_count++; +#endif + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(thread_ptr); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Lift the suspension on the previously waiting thread. */ + _tx_thread_system_resume(thread_ptr); +#endif + + /* Return a successful status. */ + status = TX_SUCCESS; + } + else + { + +#ifdef TX_NOT_INTERRUPTABLE + + /* Restore interrupts. */ + TX_RESTORE + +#else + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the disable preemption flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE +#endif + + /* Return with an error message to indicate that + nothing was done. */ + status = TX_WAIT_ABORT_ERROR; + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_time_get.c b/3rd_party/threadx/common/src/tx_time_get.c new file mode 100644 index 00000000..db44bdb5 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_time_get.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_time_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves the internal, free-running, system clock */ +/* and returns it to the caller. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* _tx_timer_system_clock Returns the system clock value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +ULONG _tx_time_get(VOID) +{ + +TX_INTERRUPT_SAVE_AREA + +#ifdef TX_ENABLE_EVENT_TRACE +ULONG another_temp_time = ((ULONG) 0); +#endif +ULONG temp_time; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup the system clock time. */ + temp_time = _tx_timer_system_clock; + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_GET, TX_ULONG_TO_POINTER_CONVERT(temp_time), TX_POINTER_TO_ULONG_CONVERT(&another_temp_time), 0, 0, TX_TRACE_TIME_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIME_GET_INSERT + + /* Restore interrupts. */ + TX_RESTORE + + /* Return the time. */ + return(temp_time); +} + diff --git a/3rd_party/threadx/common/src/tx_time_set.c b/3rd_party/threadx/common/src/tx_time_set.c new file mode 100644 index 00000000..13856cef --- /dev/null +++ b/3rd_party/threadx/common/src/tx_time_set.c @@ -0,0 +1,94 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_time_set PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function modifies the internal, free-running, system clock */ +/* as specified by the caller. */ +/* */ +/* INPUT */ +/* */ +/* new_time New time value */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_time_set(ULONG new_time) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SET, TX_ULONG_TO_POINTER_CONVERT(new_time), 0, 0, 0, TX_TRACE_TIME_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIME_SET_INSERT + + /* Set the system clock time. */ + _tx_timer_system_clock = new_time; + + /* Restore interrupts. */ + TX_RESTORE +} + diff --git a/3rd_party/threadx/common/src/tx_timer_activate.c b/3rd_party/threadx/common/src/tx_timer_activate.c new file mode 100644 index 00000000..8a9ef71c --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_activate.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_activate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the specified application timer. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Always returns success */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_system_activate Actual timer activation function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_activate(TX_TIMER *timer_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; + + + /* Disable interrupts to put the timer on the created list. */ + TX_DISABLE + +#ifdef TX_ENABLE_EVENT_TRACE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_ACTIVATE, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS) +#endif + +#ifdef TX_ENABLE_EVENT_LOGGING + + /* Log this kernel call. */ + TX_EL_TIMER_ACTIVATE_INSERT +#endif + + /* Check for an already active timer. */ + if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head != TX_NULL) + { + + /* Timer is already active, return an error. */ + status = TX_ACTIVATE_ERROR; + } + + /* Check for a timer with a zero expiration. */ + else if (timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks == ((ULONG) 0)) + { + + /* Timer is being activated with a zero expiration. */ + status = TX_ACTIVATE_ERROR; + } + else + { + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total activations counter. */ + _tx_timer_performance_activate_count++; + + /* Increment the number of activations on this timer. */ + timer_ptr -> tx_timer_performance_activate_count++; +#endif + + /* Call actual activation function. */ + _tx_timer_system_activate(&(timer_ptr -> tx_timer_internal)); + + /* Return a successful status. */ + status = TX_SUCCESS; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_change.c b/3rd_party/threadx/common/src/tx_timer_change.c new file mode 100644 index 00000000..d051078e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_change.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function modifies an application timer as specified by the */ +/* input. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* initial_ticks Initial expiration ticks */ +/* reschedule_ticks Reschedule ticks */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts to put the timer on the created list. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_CHANGE, timer_ptr, initial_ticks, reschedule_ticks, 0, TX_TRACE_TIMER_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIMER_CHANGE_INSERT + + /* Determine if the timer is active. */ + if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head == TX_NULL) + { + + /* Setup the new expiration fields. */ + timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks = initial_ticks; + timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks = reschedule_ticks; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_create.c b/3rd_party/threadx/common/src/tx_timer_create.c new file mode 100644 index 00000000..9326d69a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_create.c @@ -0,0 +1,169 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates an application timer from the specified */ +/* input. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* name_ptr Pointer to timer name */ +/* expiration_function Application expiration function */ +/* initial_ticks Initial expiration ticks */ +/* reschedule_ticks Reschedule ticks */ +/* auto_activate Automatic activation flag */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_system_activate Timer activation function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, + VOID (*expiration_function)(ULONG id), ULONG expiration_input, + ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_TIMER *next_timer; +TX_TIMER *previous_timer; + + + /* Initialize timer control block to all zeros. */ + TX_MEMSET(timer_ptr, 0, (sizeof(TX_TIMER))); + + /* Setup the basic timer fields. */ + timer_ptr -> tx_timer_name = name_ptr; + timer_ptr -> tx_timer_internal.tx_timer_internal_remaining_ticks = initial_ticks; + timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks = reschedule_ticks; + timer_ptr -> tx_timer_internal.tx_timer_internal_timeout_function = expiration_function; + timer_ptr -> tx_timer_internal.tx_timer_internal_timeout_param = expiration_input; + + /* Disable interrupts to put the timer on the created list. */ + TX_DISABLE + + /* Setup the timer ID to make it valid. */ + timer_ptr -> tx_timer_id = TX_TIMER_ID; + + /* Place the timer on the list of created application timers. First, + check for an empty list. */ + if (_tx_timer_created_count == TX_EMPTY) + { + + /* The created timer list is empty. Add timer to empty list. */ + _tx_timer_created_ptr = timer_ptr; + timer_ptr -> tx_timer_created_next = timer_ptr; + timer_ptr -> tx_timer_created_previous = timer_ptr; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_timer = _tx_timer_created_ptr; + previous_timer = next_timer -> tx_timer_created_previous; + + /* Place the new timer in the list. */ + next_timer -> tx_timer_created_previous = timer_ptr; + previous_timer -> tx_timer_created_next = timer_ptr; + + /* Setup this timer's created links. */ + timer_ptr -> tx_timer_created_previous = previous_timer; + timer_ptr -> tx_timer_created_next = next_timer; + } + + /* Increment the number of created timers. */ + _tx_timer_created_count++; + + /* Optional timer create extended processing. */ + TX_TIMER_CREATE_EXTENSION(timer_ptr) + + /* If trace is enabled, register this object. */ + TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_TIMER, timer_ptr, name_ptr, initial_ticks, reschedule_ticks) + + /* If trace is enabled, insert this call in the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_CREATE, timer_ptr, initial_ticks, reschedule_ticks, auto_activate, TX_TRACE_TIMER_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIMER_CREATE_INSERT + + /* Determine if this timer needs to be activated. */ + if (auto_activate == TX_AUTO_ACTIVATE) + { + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total activations counter. */ + _tx_timer_performance_activate_count++; + + /* Increment the number of activations on this timer. */ + timer_ptr -> tx_timer_performance_activate_count++; +#endif + + /* Call actual activation function. */ + _tx_timer_system_activate(&(timer_ptr -> tx_timer_internal)); + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_deactivate.c b/3rd_party/threadx/common/src/tx_timer_deactivate.c new file mode 100644 index 00000000..25175cc6 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_deactivate.c @@ -0,0 +1,252 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_deactivate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivates the specified application timer. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Always returns success */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_deactivate(TX_TIMER *timer_ptr) +{ +TX_INTERRUPT_SAVE_AREA + +TX_TIMER_INTERNAL *internal_ptr; +TX_TIMER_INTERNAL **list_head; +TX_TIMER_INTERNAL *next_timer; +TX_TIMER_INTERNAL *previous_timer; +ULONG ticks_left; +UINT active_timer_list; + + + /* Setup internal timer pointer. */ + internal_ptr = &(timer_ptr -> tx_timer_internal); + + /* Disable interrupts while the remaining time before expiration is + calculated. */ + TX_DISABLE + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total deactivations counter. */ + _tx_timer_performance_deactivate_count++; + + /* Increment the number of deactivations on this timer. */ + timer_ptr -> tx_timer_performance_deactivate_count++; +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_DEACTIVATE, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIMER_DEACTIVATE_INSERT + + /* Pickup the list head. */ + list_head = internal_ptr -> tx_timer_internal_list_head; + + /* Is the timer active? */ + if (list_head != TX_NULL) + { + + /* Default the active timer list flag to false. */ + active_timer_list = TX_FALSE; + + /* Determine if the head pointer is within the timer expiration list. */ + if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_start)) + { + + /* Now check to make sure the list head is before the end of the list. */ + if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) < TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) + { + + /* Set the active timer list flag to true. */ + active_timer_list = TX_TRUE; + } + } + + /* Determine if the timer is on active timer list. */ + if (active_timer_list == TX_TRUE) + { + + /* This timer is active and has not yet expired. */ + + /* Calculate the amount of time that has elapsed since the timer + was activated. */ + + /* Is this timer's entry after the current timer pointer? */ + if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(list_head) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_current_ptr)) + { + + /* Calculate ticks left to expiration - just the difference between this + timer's entry and the current timer pointer. */ + ticks_left = (ULONG) (TX_TIMER_POINTER_DIF(list_head,_tx_timer_current_ptr)) + ((ULONG) 1); + } + else + { + + /* Calculate the ticks left with a wrapped list condition. */ + ticks_left = (ULONG) (TX_TIMER_POINTER_DIF(list_head,_tx_timer_list_start)); + + ticks_left = ticks_left + (ULONG) ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1)); + } + + /* Adjust the remaining ticks accordingly. */ + if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Subtract off the last full pass through the timer list and add the + time left. */ + internal_ptr -> tx_timer_internal_remaining_ticks = + (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left; + } + else + { + + /* Just put the ticks left into the timer's remaining ticks. */ + internal_ptr -> tx_timer_internal_remaining_ticks = ticks_left; + } + } + else + { + + /* Determine if this is timer has just expired. */ + if (_tx_timer_expired_timer_ptr != internal_ptr) + { + + /* No, it hasn't expired. Now check for remaining time greater than the list + size. */ + if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Adjust the remaining ticks. */ + internal_ptr -> tx_timer_internal_remaining_ticks = + internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; + } + else + { + + /* Set the remaining time to the reactivation time. */ + internal_ptr -> tx_timer_internal_remaining_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks; + } + } + else + { + + /* Set the remaining time to the reactivation time. */ + internal_ptr -> tx_timer_internal_remaining_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks; + } + } + + /* Pickup the next timer. */ + next_timer = internal_ptr -> tx_timer_internal_active_next; + + /* See if this is the only timer in the list. */ + if (internal_ptr == next_timer) + { + + /* Yes, the only timer on the list. */ + + /* Determine if the head pointer needs to be updated. */ + if (*(list_head) == internal_ptr) + { + + /* Update the head pointer. */ + *(list_head) = TX_NULL; + } + } + else + { + + /* At least one more timer is on the same expiration list. */ + + /* Update the links of the adjacent timers. */ + previous_timer = internal_ptr -> tx_timer_internal_active_previous; + next_timer -> tx_timer_internal_active_previous = previous_timer; + previous_timer -> tx_timer_internal_active_next = next_timer; + + /* Determine if the head pointer needs to be updated. */ + if (*(list_head) == internal_ptr) + { + + /* Update the next timer in the list with the list head + pointer. */ + next_timer -> tx_timer_internal_list_head = list_head; + + /* Update the head pointer. */ + *(list_head) = next_timer; + } + } + + /* Clear the timer's list head pointer. */ + internal_ptr -> tx_timer_internal_list_head = TX_NULL; + } + + /* Restore interrupts to previous posture. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_delete.c b/3rd_party/threadx/common/src/tx_timer_delete.c new file mode 100644 index 00000000..ba9d9417 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_delete.c @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified application timer. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Successful completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_system_deactivate Timer deactivation function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_delete(TX_TIMER *timer_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_TIMER *next_timer; +TX_TIMER *previous_timer; + + + /* Disable interrupts to remove the timer from the created list. */ + TX_DISABLE + + /* Determine if the timer needs to be deactivated. */ + if (timer_ptr -> tx_timer_internal.tx_timer_internal_list_head != TX_NULL) + { + + /* Yes, deactivate the timer before it is deleted. */ + _tx_timer_system_deactivate(&(timer_ptr -> tx_timer_internal)); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_DELETE, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS) + + /* Optional timer delete extended processing. */ + TX_TIMER_DELETE_EXTENSION(timer_ptr) + + /* If trace is enabled, unregister this object. */ + TX_TRACE_OBJECT_UNREGISTER(timer_ptr) + + /* Log this kernel call. */ + TX_EL_TIMER_DELETE_INSERT + + /* Clear the timer ID to make it invalid. */ + timer_ptr -> tx_timer_id = TX_CLEAR_ID; + + /* Decrement the number of created timers. */ + _tx_timer_created_count--; + + /* See if the timer is the only one on the list. */ + if (_tx_timer_created_count == TX_EMPTY) + { + + /* Only created timer, just set the created list to NULL. */ + _tx_timer_created_ptr = TX_NULL; + } + else + { + + /* Link-up the neighbors. */ + next_timer = timer_ptr -> tx_timer_created_next; + previous_timer = timer_ptr -> tx_timer_created_previous; + next_timer -> tx_timer_created_previous = previous_timer; + previous_timer -> tx_timer_created_next = next_timer; + + /* See if we have to update the created list head pointer. */ + if (_tx_timer_created_ptr == timer_ptr) + { + + /* Yes, move the head pointer to the next link. */ + _tx_timer_created_ptr = next_timer; + } + } + + /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */ + TX_TIMER_DELETE_PORT_COMPLETION(timer_ptr) + + /* Restore interrupts. */ + TX_RESTORE + + /* Return TX_SUCCESS. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_expiration_process.c b/3rd_party/threadx/common/src/tx_timer_expiration_process.c new file mode 100644 index 00000000..c5b6e62a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_expiration_process.c @@ -0,0 +1,483 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#ifndef TX_NO_TIMER + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_expiration_process PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes thread and application timer expirations. */ +/* It is called from the _tx_timer_interrupt handler and either */ +/* processes the timer expiration in the ISR or defers to the system */ +/* timer thread. The actual processing is determined during */ +/* compilation. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_resume Thread resume processing */ +/* _tx_thread_system_ni_resume Non-interruptable resume thread */ +/* _tx_timer_system_activate Timer reactivate processing */ +/* Timer Expiration Function */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_timer_interrupt Timer interrupt handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Scott Larson Modified comment(s), and */ +/* opt out of function when */ +/* TX_NO_TIMER is defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_timer_expiration_process(VOID) +{ + +TX_INTERRUPT_SAVE_AREA + +#ifdef TX_TIMER_PROCESS_IN_ISR + +TX_TIMER_INTERNAL *expired_timers; +TX_TIMER_INTERNAL *reactivate_timer; +TX_TIMER_INTERNAL *next_timer; +TX_TIMER_INTERNAL *previous_timer; +#ifdef TX_REACTIVATE_INLINE +TX_TIMER_INTERNAL **timer_list; /* Timer list pointer */ +UINT expiration_time; /* Value used for pointer offset*/ +ULONG delta; +#endif +TX_TIMER_INTERNAL *current_timer; +VOID (*timeout_function)(ULONG id); +ULONG timeout_param = ((ULONG) 0); +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO +TX_TIMER *timer_ptr; +#endif +#endif + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Don't process in the ISR, wakeup the system timer thread to process the + timer expiration. */ + + /* Disable interrupts. */ + TX_DISABLE + +#ifdef TX_NOT_INTERRUPTABLE + + /* Resume the thread! */ + _tx_thread_system_ni_resume(&_tx_timer_thread); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call the system resume function to activate the timer thread. */ + _tx_thread_system_resume(&_tx_timer_thread); +#endif + +#else + + /* Process the timer expiration directly in the ISR. This increases the interrupt + processing, however, it eliminates the need for a system timer thread and associated + resources. */ + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if the timer processing is already active. This needs to be checked outside + of the processing loop because it remains set throughout nested timer interrupt conditions. */ + if (_tx_timer_processing_active == TX_FALSE) + { + + /* Timer processing is not nested. */ + + /* Determine if the timer expiration has already been cleared. */ + if (_tx_timer_expired != ((UINT) 0)) + { + + /* Proceed with timer processing. */ + + /* Set the timer interrupt processing active flag. */ + _tx_timer_processing_active = TX_TRUE; + + /* Now go into an infinite loop to process timer expirations. */ + do + { + + /* First, move the current list pointer and clear the timer + expired value. This allows the interrupt handling portion + to continue looking for timer expirations. */ + + /* Save the current timer expiration list pointer. */ + expired_timers = *_tx_timer_current_ptr; + + /* Modify the head pointer in the first timer in the list, if there + is one! */ + if (expired_timers != TX_NULL) + { + + expired_timers -> tx_timer_internal_list_head = &expired_timers; + } + + /* Set the current list pointer to NULL. */ + *_tx_timer_current_ptr = TX_NULL; + + /* Move the current pointer up one timer entry wrap if we get to + the end of the list. */ + _tx_timer_current_ptr = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1); + if (_tx_timer_current_ptr == _tx_timer_list_end) + { + + _tx_timer_current_ptr = _tx_timer_list_start; + } + + /* Clear the expired flag. */ + _tx_timer_expired = TX_FALSE; + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Next, process the expiration of the associated timers at this + time slot. */ + while (expired_timers != TX_NULL) + { + + /* Something is on the list. Remove it and process the expiration. */ + current_timer = expired_timers; + + /* Pickup the next timer. */ + next_timer = expired_timers -> tx_timer_internal_active_next; + + /* Set the reactivate timer to NULL. */ + reactivate_timer = TX_NULL; + + /* Determine if this is the only timer. */ + if (current_timer == next_timer) + { + + /* Yes, this is the only timer in the list. */ + + /* Set the head pointer to NULL. */ + expired_timers = TX_NULL; + } + else + { + + /* No, not the only expired timer. */ + + /* Remove this timer from the expired list. */ + previous_timer = current_timer -> tx_timer_internal_active_previous; + next_timer -> tx_timer_internal_active_previous = previous_timer; + previous_timer -> tx_timer_internal_active_next = next_timer; + + /* Modify the next timer's list head to point at the current list head. */ + next_timer -> tx_timer_internal_list_head = &expired_timers; + + /* Set the list head pointer. */ + expired_timers = next_timer; + } + + /* In any case, the timer is now off of the expired list. */ + + /* Determine if the timer has expired or if it is just a really + big timer that needs to be placed in the list again. */ + if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Timer is bigger than the timer entries and must be + rescheduled. */ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total expiration adjustments counter. */ + _tx_timer_performance__expiration_adjust_count++; + + /* Determine if this is an application timer. */ + if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) + { + + /* Derive the application timer pointer. */ + + /* Pickup the application timer pointer. */ + TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) + + /* Increment the number of expiration adjustments on this timer. */ + if (timer_ptr -> tx_timer_id == TX_TIMER_ID) + { + + timer_ptr -> tx_timer_performance__expiration_adjust_count++; + } + } +#endif + + /* Decrement the remaining ticks of the timer. */ + current_timer -> tx_timer_internal_remaining_ticks = + current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; + + /* Set the timeout function to NULL in order to bypass the + expiration. */ + timeout_function = TX_NULL; + + /* Make the timer appear that it is still active while interrupts + are enabled. This will permit proper processing of a timer + deactivate from an ISR. */ + current_timer -> tx_timer_internal_list_head = &reactivate_timer; + current_timer -> tx_timer_internal_active_next = current_timer; + + /* Setup the temporary timer list head pointer. */ + reactivate_timer = current_timer; + } + else + { + + /* Timer did expire. */ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total expirations counter. */ + _tx_timer_performance_expiration_count++; + + /* Determine if this is an application timer. */ + if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) + { + + /* Derive the application timer pointer. */ + + /* Pickup the application timer pointer. */ + TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) + + /* Increment the number of expirations on this timer. */ + if (timer_ptr -> tx_timer_id == TX_TIMER_ID) + { + + timer_ptr -> tx_timer_performance_expiration_count++; + } + } +#endif + + /* Copy the calling function and ID into local variables before interrupts + are re-enabled. */ + timeout_function = current_timer -> tx_timer_internal_timeout_function; + timeout_param = current_timer -> tx_timer_internal_timeout_param; + + /* Copy the reinitialize ticks into the remaining ticks. */ + current_timer -> tx_timer_internal_remaining_ticks = current_timer -> tx_timer_internal_re_initialize_ticks; + + /* Determine if the timer should be reactivated. */ + if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0)) + { + + /* Make the timer appear that it is still active while processing + the expiration routine and with interrupts enabled. This will + permit proper processing of a timer deactivate from both the + expiration routine and an ISR. */ + current_timer -> tx_timer_internal_list_head = &reactivate_timer; + current_timer -> tx_timer_internal_active_next = current_timer; + + /* Setup the temporary timer list head pointer. */ + reactivate_timer = current_timer; + } + else + { + + /* Set the list pointer of this timer to NULL. This is used to indicate + the timer is no longer active. */ + current_timer -> tx_timer_internal_list_head = TX_NULL; + } + } + + /* Set pointer to indicate the expired timer that is currently being processed. */ + _tx_timer_expired_timer_ptr = current_timer; + + /* Restore interrupts for timer expiration call. */ + TX_RESTORE + + /* Call the timer-expiration function, if non-NULL. */ + if (timeout_function != TX_NULL) + { + + (timeout_function) (timeout_param); + } + + /* Lockout interrupts again. */ + TX_DISABLE + + /* Clear expired timer pointer. */ + _tx_timer_expired_timer_ptr = TX_NULL; + + /* Determine if the timer needs to be reactivated. */ + if (reactivate_timer == current_timer) + { + + /* Reactivate the timer. */ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Determine if this timer expired. */ + if (timeout_function != TX_NULL) + { + + /* Increment the total reactivations counter. */ + _tx_timer_performance_reactivate_count++; + + /* Determine if this is an application timer. */ + if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) + { + + /* Derive the application timer pointer. */ + + /* Pickup the application timer pointer. */ + TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) + + /* Increment the number of expirations on this timer. */ + if (timer_ptr -> tx_timer_id == TX_TIMER_ID) + { + + timer_ptr -> tx_timer_performance_reactivate_count++; + } + } + } +#endif + + +#ifdef TX_REACTIVATE_INLINE + + /* Calculate the amount of time remaining for the timer. */ + if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Set expiration time to the maximum number of entries. */ + expiration_time = TX_TIMER_ENTRIES - ((UINT) 1); + } + else + { + + /* Timer value fits in the timer entries. */ + + /* Set the expiration time. */ + expiration_time = ((UINT) current_timer -> tx_timer_internal_remaining_ticks) - ((UINT) 1); + } + + /* At this point, we are ready to put the timer back on one of + the timer lists. */ + + /* Calculate the proper place for the timer. */ + timer_list = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time); + if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) + { + + /* Wrap from the beginning of the list. */ + delta = TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end); + timer_list = TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta); + } + + /* Now put the timer on this list. */ + if ((*timer_list) == TX_NULL) + { + + /* This list is NULL, just put the new timer on it. */ + + /* Setup the links in this timer. */ + current_timer -> tx_timer_internal_active_next = current_timer; + current_timer -> tx_timer_internal_active_previous = current_timer; + + /* Setup the list head pointer. */ + *timer_list = current_timer; + } + else + { + + /* This list is not NULL, add current timer to the end. */ + next_timer = *timer_list; + previous_timer = next_timer -> tx_timer_internal_active_previous; + previous_timer -> tx_timer_internal_active_next = current_timer; + next_timer -> tx_timer_internal_active_previous = current_timer; + current_timer -> tx_timer_internal_active_next = next_timer; + current_timer -> tx_timer_internal_active_previous = previous_timer; + } + + /* Setup list head pointer. */ + current_timer -> tx_timer_internal_list_head = timer_list; +#else + + /* Reactivate through the timer activate function. */ + + /* Clear the list head for the timer activate call. */ + current_timer -> tx_timer_internal_list_head = TX_NULL; + + /* Activate the current timer. */ + _tx_timer_system_activate(current_timer); +#endif + } + } + } while (_tx_timer_expired != TX_FALSE); + + /* Clear the timer interrupt processing active flag. */ + _tx_timer_processing_active = TX_FALSE; + } + } + + /* Restore interrupts. */ + TX_RESTORE +#endif +} + +#endif diff --git a/3rd_party/threadx/common/src/tx_timer_info_get.c b/3rd_party/threadx/common/src/tx_timer_info_get.c new file mode 100644 index 00000000..aba17b6b --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_info_get.c @@ -0,0 +1,250 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves information from the specified timer. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* name Destination for the timer name */ +/* active Destination for active flag */ +/* remaining_ticks Destination for remaining ticks */ +/* before expiration */ +/* reschedule_ticks Destination for reschedule ticks */ +/* next_timer Destination for next timer on the */ +/* created list */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, + ULONG *reschedule_ticks, TX_TIMER **next_timer) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_TIMER_INTERNAL *internal_ptr; +TX_TIMER_INTERNAL **list_head; +ULONG ticks_left; +UINT timer_active; +UINT active_timer_list; + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_INFO_GET, timer_ptr, TX_POINTER_TO_ULONG_CONVERT(&ticks_left), 0, 0, TX_TRACE_TIMER_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIMER_INFO_GET_INSERT + + /* Retrieve the name of the timer. */ + if (name != TX_NULL) + { + + *name = timer_ptr -> tx_timer_name; + } + + /* Pickup address of internal timer structure. */ + internal_ptr = &(timer_ptr -> tx_timer_internal); + + /* Retrieve all the pertinent information and return it in the supplied + destinations. */ + + /* Default active to false. */ + timer_active = TX_FALSE; + + /* Default the ticks left to the remaining ticks. */ + ticks_left = internal_ptr -> tx_timer_internal_remaining_ticks; + + /* Determine if the timer is still active. */ + if (internal_ptr -> tx_timer_internal_list_head != TX_NULL) + { + + /* Indicate this timer is active. */ + timer_active = TX_TRUE; + + /* Default the active timer list flag to false. */ + active_timer_list = TX_FALSE; + + /* Determine if the timer is still active. */ + if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_list_start) + { + + /* Determine if the list head is before the end of the list. */ + if (internal_ptr -> tx_timer_internal_list_head < _tx_timer_list_end) + { + + /* This timer is active and has not yet expired. */ + active_timer_list = TX_TRUE; + } + } + + /* Determine if the timer is on the active timer list. */ + if (active_timer_list == TX_TRUE) + { + + /* Calculate the amount of time that has elapsed since the timer + was activated. */ + + /* Setup the list head pointer. */ + list_head = internal_ptr -> tx_timer_internal_list_head; + + /* Is this timer's entry after the current timer pointer? */ + if (internal_ptr -> tx_timer_internal_list_head >= _tx_timer_current_ptr) + { + + /* Calculate ticks left to expiration - just the difference between this + timer's entry and the current timer pointer. */ + ticks_left = ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_current_ptr)) + ((ULONG) 1)); + } + else + { + + /* Calculate the ticks left with a wrapped list condition. */ + ticks_left = ((TX_TIMER_POINTER_DIF(list_head, _tx_timer_list_start))); + + ticks_left = ticks_left + ((TX_TIMER_POINTER_DIF(_tx_timer_list_end, _tx_timer_current_ptr)) + ((ULONG) 1)); + } + + /* Adjust the remaining ticks accordingly. */ + if (internal_ptr -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Subtract off the last full pass through the timer list and add the + time left. */ + ticks_left = (internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES) + ticks_left; + } + + } + else + { + + /* The timer is not on the actual timer list so it must either be being processed + or on a temporary list to be processed. */ + + /* Check to see if this timer is the timer currently being processed. */ + if (_tx_timer_expired_timer_ptr == internal_ptr) + { + + /* Timer dispatch routine is executing, waiting to execute, or just finishing. No more remaining ticks for this expiration. */ + ticks_left = ((ULONG) 0); + } + else + { + + /* Timer is not the one being processed, which means it must be on the temporary expiration list + waiting to be processed. */ + + /* Calculate the remaining ticks for a timer in the process of expiring. */ + if (ticks_left > TX_TIMER_ENTRIES) + { + + /* Calculate the number of ticks remaining. */ + ticks_left = internal_ptr -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; + } + else + { + + /* Timer dispatch routine is waiting to execute, no more remaining ticks for this expiration. */ + ticks_left = ((ULONG) 0); + } + } + } + } + + /* Setup return values for an inactive timer. */ + if (active != TX_NULL) + { + + /* Setup the timer active indication. */ + *active = timer_active; + } + if (remaining_ticks != TX_NULL) + { + + /* Setup the default remaining ticks value. */ + *remaining_ticks = ticks_left; + } + + /* Pickup the reschedule ticks value. */ + if (reschedule_ticks != TX_NULL) + { + + *reschedule_ticks = internal_ptr -> tx_timer_internal_re_initialize_ticks; + } + + /* Pickup the next created application timer. */ + if (next_timer != TX_NULL) + { + + *next_timer = timer_ptr -> tx_timer_created_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_initialize.c b/3rd_party/threadx/common/src/tx_timer_initialize.c new file mode 100644 index 00000000..564c005a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_initialize.c @@ -0,0 +1,306 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/* Check for the TX_NO_TIMER option. When defined, do not define all of the + timer component global variables. */ + +#ifndef TX_NO_TIMER + + +/* Define the system clock value that is continually incremented by the + periodic timer interrupt processing. */ + +volatile ULONG _tx_timer_system_clock; + + +/* Define the time-slice expiration flag. This is used to indicate that a time-slice + has happened. */ + +UINT _tx_timer_expired_time_slice; + + +/* Define the thread and application timer entry list. This list provides a direct access + method for insertion of times less than TX_TIMER_ENTRIES. */ + +TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES]; + + +/* Define the boundary pointers to the list. These are setup to easily manage + wrapping the list. */ + +TX_TIMER_INTERNAL **_tx_timer_list_start; +TX_TIMER_INTERNAL **_tx_timer_list_end; + + +/* Define the current timer pointer in the list. This pointer is moved sequentially + through the timer list by the timer interrupt handler. */ + +TX_TIMER_INTERNAL **_tx_timer_current_ptr; + + +/* Define the timer expiration flag. This is used to indicate that a timer + has expired. */ + +UINT _tx_timer_expired; + + +/* Define the created timer list head pointer. */ + +TX_TIMER *_tx_timer_created_ptr; + + +/* Define the created timer count. */ + +ULONG _tx_timer_created_count; + + +/* Define the pointer to the timer that has expired and is being processed. */ + +TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr; + + +#ifndef TX_TIMER_PROCESS_IN_ISR + +/* Define the timer thread's control block. */ + +TX_THREAD _tx_timer_thread; + + +/* Define the variable that holds the timer thread's starting stack address. */ + +VOID *_tx_timer_stack_start; + + +/* Define the variable that holds the timer thread's stack size. */ + +ULONG _tx_timer_stack_size; + + +/* Define the variable that holds the timer thread's priority. */ + +UINT _tx_timer_priority; + +/* Define the system timer thread's stack. The default size is defined + in tx_port.h. */ + +ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG))- ((UINT) 1)))/(sizeof(ULONG))]; + +#else + + +/* Define the busy flag that will prevent nested timer ISR processing. */ + +UINT _tx_timer_processing_active; + +#endif + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + +/* Define the total number of timer activations. */ + +ULONG _tx_timer_performance_activate_count; + + +/* Define the total number of timer reactivations. */ + +ULONG _tx_timer_performance_reactivate_count; + + +/* Define the total number of timer deactivations. */ + +ULONG _tx_timer_performance_deactivate_count; + + +/* Define the total number of timer expirations. */ + +ULONG _tx_timer_performance_expiration_count; + + +/* Define the total number of timer expiration adjustments. These are required + if the expiration time is greater than the size of the timer list. In such + cases, the timer is placed at the end of the list and then reactivated + as many times as necessary to finally achieve the resulting timeout. */ + +ULONG _tx_timer_performance__expiration_adjust_count; + +#endif +#endif + + +/* Define the current time slice value. If non-zero, a time-slice is active. + Otherwise, the time_slice is not active. */ + +ULONG _tx_timer_time_slice; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the clock control component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_create Create the system timer thread */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_timer_initialize(VOID) +{ +#ifndef TX_NO_TIMER +#ifndef TX_TIMER_PROCESS_IN_ISR +UINT status; +#endif + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the system clock to 0. */ + _tx_timer_system_clock = ((ULONG) 0); + + /* Initialize the time-slice value to 0 to make sure it is disabled. */ + _tx_timer_time_slice = ((ULONG) 0); + + /* Clear the expired flags. */ + _tx_timer_expired_time_slice = TX_FALSE; + _tx_timer_expired = TX_FALSE; + + /* Set the currently expired timer being processed pointer to NULL. */ + _tx_timer_expired_timer_ptr = TX_NULL; + + /* Initialize the thread and application timer management control structures. */ + + /* First, initialize the timer list. */ + TX_MEMSET(&_tx_timer_list[0], 0, (sizeof(_tx_timer_list))); +#endif + + /* Initialize all of the list pointers. */ + _tx_timer_list_start = &_tx_timer_list[0]; + _tx_timer_current_ptr = &_tx_timer_list[0]; + + /* Set the timer list end pointer to one past the actual timer list. This is done + to make the timer interrupt handling in assembly language a little easier. */ + _tx_timer_list_end = &_tx_timer_list[TX_TIMER_ENTRIES-((ULONG) 1)]; + _tx_timer_list_end = TX_TIMER_POINTER_ADD(_tx_timer_list_end, ((ULONG) 1)); + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Setup the variables associated with the system timer thread's stack and + priority. */ + _tx_timer_stack_start = (VOID *) &_tx_timer_thread_stack_area[0]; + _tx_timer_stack_size = ((ULONG) TX_TIMER_THREAD_STACK_SIZE); + _tx_timer_priority = ((UINT) TX_TIMER_THREAD_PRIORITY); + + /* Create the system timer thread. This thread processes all of the timer + expirations and reschedules. Its stack and priority are defined in the + low-level initialization component. */ + do + { + + /* Create the system timer thread. */ + status = _tx_thread_create(&_tx_timer_thread, + TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT("System Timer Thread"), + _tx_timer_thread_entry, + ((ULONG) TX_TIMER_ID), + _tx_timer_stack_start, _tx_timer_stack_size, + _tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE, TX_DONT_START); + +#ifdef TX_SAFETY_CRITICAL + + /* Check return from thread create - if an error is detected throw an exception. */ + if (status != TX_SUCCESS) + { + + /* Raise safety critical exception. */ + TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, status); + } +#endif + + /* Define timer initialize extension. */ + TX_TIMER_INITIALIZE_EXTENSION(status) + + } while (status != TX_SUCCESS); + +#else + + /* Clear the timer interrupt processing active flag. */ + _tx_timer_processing_active = TX_FALSE; +#endif + +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize the head pointer of the created application timer list. */ + _tx_timer_created_ptr = TX_NULL; + + /* Set the created count to zero. */ + _tx_timer_created_count = TX_EMPTY; + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Initialize timer performance counters. */ + _tx_timer_performance_activate_count = ((ULONG) 0); + _tx_timer_performance_reactivate_count = ((ULONG) 0); + _tx_timer_performance_deactivate_count = ((ULONG) 0); + _tx_timer_performance_expiration_count = ((ULONG) 0); + _tx_timer_performance__expiration_adjust_count = ((ULONG) 0); +#endif +#endif +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_timer_performance_info_get.c b/3rd_party/threadx/common/src/tx_timer_performance_info_get.c new file mode 100644 index 00000000..2c0a7e6e --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_performance_info_get.c @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_performance_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves performance information from the specified */ +/* timer. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* activates Destination for the number of */ +/* activations of this timer */ +/* reactivates Destination for the number of */ +/* reactivations of this timer */ +/* deactivates Destination for the number of */ +/* deactivations of this timer */ +/* expirations Destination for the number of */ +/* expirations of this timer */ +/* expiration_adjusts Destination for the number of */ +/* expiration adjustments of this */ +/* timer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_performance_info_get(TX_TIMER *timer_ptr, ULONG *activates, ULONG *reactivates, + ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts) +{ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA +UINT status; + + + /* Determine if this is a legal request. */ + if (timer_ptr == TX_NULL) + { + + /* Timer pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + + /* Determine if the timer ID is invalid. */ + else if (timer_ptr -> tx_timer_id != TX_TIMER_ID) + { + + /* Timer pointer is illegal, return error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_PERFORMANCE_INFO_GET, timer_ptr, 0, 0, 0, TX_TRACE_TIMER_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIMER_PERFORMANCE_INFO_GET_INSERT + + /* Retrieve the number of activations of this timer. */ + if (activates != TX_NULL) + { + + *activates = timer_ptr -> tx_timer_performance_activate_count; + } + + /* Retrieve the number of reactivations of this timer. */ + if (reactivates != TX_NULL) + { + + *reactivates = timer_ptr -> tx_timer_performance_reactivate_count; + } + + /* Retrieve the number of deactivations of this timer. */ + if (deactivates != TX_NULL) + { + + *deactivates = timer_ptr -> tx_timer_performance_deactivate_count; + } + + /* Retrieve the number of expirations of this timer. */ + if (expirations != TX_NULL) + { + + *expirations = timer_ptr -> tx_timer_performance_expiration_count; + } + + /* Retrieve the number of expiration adjustments of this timer. */ + if (expiration_adjusts != TX_NULL) + { + + *expiration_adjusts = timer_ptr -> tx_timer_performance__expiration_adjust_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return successful completion. */ + status = TX_SUCCESS; + } +#else +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (timer_ptr != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (activates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (reactivates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (deactivates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (expirations != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (expiration_adjusts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } +#endif + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/tx_timer_performance_system_info_get.c b/3rd_party/threadx/common/src/tx_timer_performance_system_info_get.c new file mode 100644 index 00000000..443c10c3 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_performance_system_info_get.c @@ -0,0 +1,189 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO +#include "tx_trace.h" +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_performance_system_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves timer performance information. */ +/* */ +/* INPUT */ +/* */ +/* activates Destination for total number of */ +/* activations */ +/* reactivates Destination for total number of */ +/* reactivations */ +/* deactivates Destination for total number of */ +/* deactivations */ +/* expirations Destination for total number of */ +/* expirations */ +/* expiration_adjusts Destination for total number of */ +/* expiration adjustments */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_timer_performance_system_info_get(ULONG *activates, ULONG *reactivates, + ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts) +{ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* If trace is enabled, insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIMER_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_TIMER_EVENTS) + + /* Log this kernel call. */ + TX_EL_TIMER_PERFORMANCE_SYSTEM_INFO_GET_INSERT + + /* Retrieve the total number of timer activations. */ + if (activates != TX_NULL) + { + + *activates = _tx_timer_performance_activate_count; + } + + /* Retrieve the total number of timer reactivations. */ + if (reactivates != TX_NULL) + { + + *reactivates = _tx_timer_performance_reactivate_count; + } + + /* Retrieve the total number of timer deactivations. */ + if (deactivates != TX_NULL) + { + + *deactivates = _tx_timer_performance_deactivate_count; + } + + /* Retrieve the total number of timer expirations. */ + if (expirations != TX_NULL) + { + + *expirations = _tx_timer_performance_expiration_count; + } + + /* Retrieve the total number of timer expiration adjustments. */ + if (expiration_adjusts != TX_NULL) + { + + *expiration_adjusts = _tx_timer_performance__expiration_adjust_count; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (activates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (reactivates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (deactivates != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (expirations != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (expiration_adjusts != TX_NULL) + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Not enabled, return error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_timer_system_activate.c b/3rd_party/threadx/common/src/tx_timer_system_activate.c new file mode 100644 index 00000000..08efdf24 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_system_activate.c @@ -0,0 +1,170 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#ifndef TX_NO_TIMER + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_system_activate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function places the specified internal timer in the proper */ +/* place in the timer expiration list. If the timer is already active */ +/* this function does nothing. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Always returns success */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_system_suspend Thread suspend function */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* _tx_timer_thread_entry Timer thread processing */ +/* _tx_timer_activate Application timer activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Scott Larson Modified comment(s), and */ +/* opt out of function when */ +/* TX_NO_TIMER is defined, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr) +{ + +TX_TIMER_INTERNAL **timer_list; +TX_TIMER_INTERNAL *next_timer; +TX_TIMER_INTERNAL *previous_timer; +ULONG delta; +ULONG remaining_ticks; +ULONG expiration_time; + + + /* Pickup the remaining ticks. */ + remaining_ticks = timer_ptr -> tx_timer_internal_remaining_ticks; + + /* Determine if there is a timer to activate. */ + if (remaining_ticks != ((ULONG) 0)) + { + + /* Determine if the timer is set to wait forever. */ + if (remaining_ticks != TX_WAIT_FOREVER) + { + + /* Valid timer activate request. */ + + /* Determine if the timer still needs activation. */ + if (timer_ptr -> tx_timer_internal_list_head == TX_NULL) + { + + /* Activate the timer. */ + + /* Calculate the amount of time remaining for the timer. */ + if (remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Set expiration time to the maximum number of entries. */ + expiration_time = TX_TIMER_ENTRIES - ((ULONG) 1); + } + else + { + + /* Timer value fits in the timer entries. */ + + /* Set the expiration time. */ + expiration_time = (remaining_ticks - ((ULONG) 1)); + } + + /* At this point, we are ready to put the timer on one of + the timer lists. */ + + /* Calculate the proper place for the timer. */ + timer_list = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time); + if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) + { + + /* Wrap from the beginning of the list. */ + delta = TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end); + timer_list = TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta); + } + + /* Now put the timer on this list. */ + if ((*timer_list) == TX_NULL) + { + + /* This list is NULL, just put the new timer on it. */ + + /* Setup the links in this timer. */ + timer_ptr -> tx_timer_internal_active_next = timer_ptr; + timer_ptr -> tx_timer_internal_active_previous = timer_ptr; + + /* Setup the list head pointer. */ + *timer_list = timer_ptr; + } + else + { + + /* This list is not NULL, add current timer to the end. */ + next_timer = *timer_list; + previous_timer = next_timer -> tx_timer_internal_active_previous; + previous_timer -> tx_timer_internal_active_next = timer_ptr; + next_timer -> tx_timer_internal_active_previous = timer_ptr; + timer_ptr -> tx_timer_internal_active_next = next_timer; + timer_ptr -> tx_timer_internal_active_previous = previous_timer; + } + + /* Setup list head pointer. */ + timer_ptr -> tx_timer_internal_list_head = timer_list; + } + } + } +} + +#endif diff --git a/3rd_party/threadx/common/src/tx_timer_system_deactivate.c b/3rd_party/threadx/common/src/tx_timer_system_deactivate.c new file mode 100644 index 00000000..909bf458 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_system_deactivate.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_system_deactivate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivates, or removes the timer from the active */ +/* timer expiration list. If the timer is already deactivated, this */ +/* function just returns. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SUCCESS Always returns success */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_system_resume Thread resume function */ +/* _tx_timer_thread_entry Timer thread processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr) +{ + +TX_TIMER_INTERNAL **list_head; +TX_TIMER_INTERNAL *next_timer; +TX_TIMER_INTERNAL *previous_timer; + + + /* Pickup the list head pointer. */ + list_head = timer_ptr -> tx_timer_internal_list_head; + + /* Determine if the timer still needs deactivation. */ + if (list_head != TX_NULL) + { + + /* Deactivate the timer. */ + + /* Pickup the next active timer. */ + next_timer = timer_ptr -> tx_timer_internal_active_next; + + /* See if this is the only timer in the list. */ + if (timer_ptr == next_timer) + { + + /* Yes, the only timer on the list. */ + + /* Determine if the head pointer needs to be updated. */ + if (*(list_head) == timer_ptr) + { + + /* Update the head pointer. */ + *(list_head) = TX_NULL; + } + } + else + { + + /* At least one more timer is on the same expiration list. */ + + /* Update the links of the adjacent timers. */ + previous_timer = timer_ptr -> tx_timer_internal_active_previous; + next_timer -> tx_timer_internal_active_previous = previous_timer; + previous_timer -> tx_timer_internal_active_next = next_timer; + + /* Determine if the head pointer needs to be updated. */ + if (*(list_head) == timer_ptr) + { + + /* Update the next timer in the list with the list head pointer. */ + next_timer -> tx_timer_internal_list_head = list_head; + + /* Update the head pointer. */ + *(list_head) = next_timer; + } + } + + /* Clear the timer's list head pointer. */ + timer_ptr -> tx_timer_internal_list_head = TX_NULL; + } +} + diff --git a/3rd_party/threadx/common/src/tx_timer_thread_entry.c b/3rd_party/threadx/common/src/tx_timer_thread_entry.c new file mode 100644 index 00000000..f08f8397 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_timer_thread_entry.c @@ -0,0 +1,482 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_thread_entry PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages thread and application timer expirations. */ +/* Actually, from this thread's point of view, there is no difference. */ +/* */ +/* INPUT */ +/* */ +/* timer_thread_input Used just for verification */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* Timer Expiration Function */ +/* _tx_thread_system_suspend Thread suspension */ +/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */ +/* _tx_timer_system_activate Timer reactivate processing */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX Scheduler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +#ifndef TX_TIMER_PROCESS_IN_ISR +VOID _tx_timer_thread_entry(ULONG timer_thread_input) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_TIMER_INTERNAL *expired_timers; +TX_TIMER_INTERNAL *reactivate_timer; +TX_TIMER_INTERNAL *next_timer; +TX_TIMER_INTERNAL *previous_timer; +TX_TIMER_INTERNAL *current_timer; +VOID (*timeout_function)(ULONG id); +ULONG timeout_param = ((ULONG) 0); +TX_THREAD *thread_ptr; +#ifdef TX_REACTIVATE_INLINE +TX_TIMER_INTERNAL **timer_list; /* Timer list pointer */ +UINT expiration_time; /* Value used for pointer offset*/ +ULONG delta; +#endif +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO +TX_TIMER *timer_ptr; +#endif + + + /* Make sure the timer input is correct. This also gets rid of the + silly compiler warnings. */ + if (timer_thread_input == TX_TIMER_ID) + { + + /* Yes, valid thread entry, proceed... */ + + /* Now go into an infinite loop to process timer expirations. */ + while (TX_LOOP_FOREVER) + { + + /* First, move the current list pointer and clear the timer + expired value. This allows the interrupt handling portion + to continue looking for timer expirations. */ + TX_DISABLE + + /* Save the current timer expiration list pointer. */ + expired_timers = *_tx_timer_current_ptr; + + /* Modify the head pointer in the first timer in the list, if there + is one! */ + if (expired_timers != TX_NULL) + { + + expired_timers -> tx_timer_internal_list_head = &expired_timers; + } + + /* Set the current list pointer to NULL. */ + *_tx_timer_current_ptr = TX_NULL; + + /* Move the current pointer up one timer entry wrap if we get to + the end of the list. */ + _tx_timer_current_ptr = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1); + if (_tx_timer_current_ptr == _tx_timer_list_end) + { + + _tx_timer_current_ptr = _tx_timer_list_start; + } + + /* Clear the expired flag. */ + _tx_timer_expired = TX_FALSE; + + /* Restore interrupts temporarily. */ + TX_RESTORE + + /* Disable interrupts again. */ + TX_DISABLE + + /* Next, process the expiration of the associated timers at this + time slot. */ + while (expired_timers != TX_NULL) + { + + /* Something is on the list. Remove it and process the expiration. */ + current_timer = expired_timers; + + /* Pickup the next timer. */ + next_timer = expired_timers -> tx_timer_internal_active_next; + + /* Set the reactivate_timer to NULL. */ + reactivate_timer = TX_NULL; + + /* Determine if this is the only timer. */ + if (current_timer == next_timer) + { + + /* Yes, this is the only timer in the list. */ + + /* Set the head pointer to NULL. */ + expired_timers = TX_NULL; + } + else + { + + /* No, not the only expired timer. */ + + /* Remove this timer from the expired list. */ + previous_timer = current_timer -> tx_timer_internal_active_previous; + next_timer -> tx_timer_internal_active_previous = previous_timer; + previous_timer -> tx_timer_internal_active_next = next_timer; + + /* Modify the next timer's list head to point at the current list head. */ + next_timer -> tx_timer_internal_list_head = &expired_timers; + + /* Set the list head pointer. */ + expired_timers = next_timer; + } + + /* In any case, the timer is now off of the expired list. */ + + /* Determine if the timer has expired or if it is just a really + big timer that needs to be placed in the list again. */ + if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Timer is bigger than the timer entries and must be + rescheduled. */ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total expiration adjustments counter. */ + _tx_timer_performance__expiration_adjust_count++; + + /* Determine if this is an application timer. */ + if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) + { + + /* Derive the application timer pointer. */ + + /* Pickup the application timer pointer. */ + TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) + + /* Increment the number of expiration adjustments on this timer. */ + if (timer_ptr -> tx_timer_id == TX_TIMER_ID) + { + + timer_ptr -> tx_timer_performance__expiration_adjust_count++; + } + } +#endif + + /* Decrement the remaining ticks of the timer. */ + current_timer -> tx_timer_internal_remaining_ticks = + current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES; + + /* Set the timeout function to NULL in order to bypass the + expiration. */ + timeout_function = TX_NULL; + + /* Make the timer appear that it is still active while interrupts + are enabled. This will permit proper processing of a timer + deactivate from an ISR. */ + current_timer -> tx_timer_internal_list_head = &reactivate_timer; + current_timer -> tx_timer_internal_active_next = current_timer; + + /* Setup the temporary timer list head pointer. */ + reactivate_timer = current_timer; + } + else + { + + /* Timer did expire. */ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Increment the total expirations counter. */ + _tx_timer_performance_expiration_count++; + + /* Determine if this is an application timer. */ + if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) + { + + /* Derive the application timer pointer. */ + + /* Pickup the application timer pointer. */ + TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) + + /* Increment the number of expirations on this timer. */ + if (timer_ptr -> tx_timer_id == TX_TIMER_ID) + { + + timer_ptr -> tx_timer_performance_expiration_count++; + } + } +#endif + + /* Copy the calling function and ID into local variables before interrupts + are re-enabled. */ + timeout_function = current_timer -> tx_timer_internal_timeout_function; + timeout_param = current_timer -> tx_timer_internal_timeout_param; + + /* Copy the reinitialize ticks into the remaining ticks. */ + current_timer -> tx_timer_internal_remaining_ticks = current_timer -> tx_timer_internal_re_initialize_ticks; + + /* Determine if the timer should be reactivated. */ + if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0)) + { + + /* Make the timer appear that it is still active while processing + the expiration routine and with interrupts enabled. This will + permit proper processing of a timer deactivate from both the + expiration routine and an ISR. */ + current_timer -> tx_timer_internal_list_head = &reactivate_timer; + current_timer -> tx_timer_internal_active_next = current_timer; + + /* Setup the temporary timer list head pointer. */ + reactivate_timer = current_timer; + } + else + { + + /* Set the list pointer of this timer to NULL. This is used to indicate + the timer is no longer active. */ + current_timer -> tx_timer_internal_list_head = TX_NULL; + } + } + + /* Set pointer to indicate the expired timer that is currently being processed. */ + _tx_timer_expired_timer_ptr = current_timer; + + /* Restore interrupts for timer expiration call. */ + TX_RESTORE + + /* Call the timer-expiration function, if non-NULL. */ + if (timeout_function != TX_NULL) + { + + (timeout_function) (timeout_param); + } + + /* Lockout interrupts again. */ + TX_DISABLE + + /* Clear expired timer pointer. */ + _tx_timer_expired_timer_ptr = TX_NULL; + + /* Determine if the timer needs to be reactivated. */ + if (reactivate_timer == current_timer) + { + + /* Reactivate the timer. */ + +#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO + + /* Determine if this timer expired. */ + if (timeout_function != TX_NULL) + { + + /* Increment the total reactivations counter. */ + _tx_timer_performance_reactivate_count++; + + /* Determine if this is an application timer. */ + if (current_timer -> tx_timer_internal_timeout_function != &_tx_thread_timeout) + { + + /* Derive the application timer pointer. */ + + /* Pickup the application timer pointer. */ + TX_USER_TIMER_POINTER_GET(current_timer, timer_ptr) + + /* Increment the number of expirations on this timer. */ + if (timer_ptr -> tx_timer_id == TX_TIMER_ID) + { + + timer_ptr -> tx_timer_performance_reactivate_count++; + } + } + } +#endif + +#ifdef TX_REACTIVATE_INLINE + + /* Calculate the amount of time remaining for the timer. */ + if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES) + { + + /* Set expiration time to the maximum number of entries. */ + expiration_time = TX_TIMER_ENTRIES - ((UINT) 1); + } + else + { + + /* Timer value fits in the timer entries. */ + + /* Set the expiration time. */ + expiration_time = ((UINT) current_timer -> tx_timer_internal_remaining_ticks) - ((UINT) 1); + } + + /* At this point, we are ready to put the timer back on one of + the timer lists. */ + + /* Calculate the proper place for the timer. */ + timer_list = TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time); + if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end)) + { + + /* Wrap from the beginning of the list. */ + delta = TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end); + timer_list = TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta); + } + + /* Now put the timer on this list. */ + if ((*timer_list) == TX_NULL) + { + + /* This list is NULL, just put the new timer on it. */ + + /* Setup the links in this timer. */ + current_timer -> tx_timer_internal_active_next = current_timer; + current_timer -> tx_timer_internal_active_previous = current_timer; + + /* Setup the list head pointer. */ + *timer_list = current_timer; + } + else + { + + /* This list is not NULL, add current timer to the end. */ + next_timer = *timer_list; + previous_timer = next_timer -> tx_timer_internal_active_previous; + previous_timer -> tx_timer_internal_active_next = current_timer; + next_timer -> tx_timer_internal_active_previous = current_timer; + current_timer -> tx_timer_internal_active_next = next_timer; + current_timer -> tx_timer_internal_active_previous = previous_timer; + } + + /* Setup list head pointer. */ + current_timer -> tx_timer_internal_list_head = timer_list; +#else + + /* Reactivate through the timer activate function. */ + + /* Clear the list head for the timer activate call. */ + current_timer -> tx_timer_internal_list_head = TX_NULL; + + /* Activate the current timer. */ + _tx_timer_system_activate(current_timer); +#endif + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Lockout interrupts again. */ + TX_DISABLE + } + + /* Finally, suspend this thread and wait for the next expiration. */ + + /* Determine if another expiration took place while we were in this + thread. If so, process another expiration. */ + if (_tx_timer_expired == TX_FALSE) + { + + /* Otherwise, no timer expiration, so suspend the thread. */ + + /* Build pointer to the timer thread. */ + thread_ptr = &_tx_timer_thread; + + /* Set the status to suspending, in order to indicate the + suspension is in progress. */ + thread_ptr -> tx_thread_state = TX_SUSPENDED; + +#ifdef TX_NOT_INTERRUPTABLE + + /* Call actual non-interruptable thread suspension routine. */ + _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Set the suspending flag. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + + /* Increment the preempt disable count prior to suspending. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Call actual thread suspension routine. */ + _tx_thread_system_suspend(thread_ptr); +#endif + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + } + } + } + +#ifdef TX_SAFETY_CRITICAL + + /* If we ever get here, raise safety critical exception. */ + TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); +#endif + +} +#endif + diff --git a/3rd_party/threadx/common/src/tx_trace_buffer_full_notify.c b/3rd_party/threadx/common/src/tx_trace_buffer_full_notify.c new file mode 100644 index 00000000..383b134a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_buffer_full_notify.c @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef TX_SOURCE_CODE +#define TX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_buffer_full_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets up the application callback function that is */ +/* called whenever the trace buffer becomes full. The application */ +/* can then swap to a new trace buffer in order not to lose any */ +/* events. */ +/* */ +/* INPUT */ +/* */ +/* full_buffer_callback Full trace buffer processing */ +/* function */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_buffer_full_notify(VOID (*full_buffer_callback)(VOID *buffer)) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Setup the callback function pointer. */ + _tx_trace_full_notify_function = full_buffer_callback; + + /* Return success. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (full_buffer_callback != TX_NULL) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_disable.c b/3rd_party/threadx/common/src/tx_trace_disable.c new file mode 100644 index 00000000..dbf8f3b2 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_disable.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_disable PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function disables trace inside of ThreadX. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_disable(VOID) +{ + +#ifdef TX_ENABLE_EVENT_TRACE +UINT status; + + + /* Determine if trace is already disabled. */ + if (_tx_trace_buffer_current_ptr == TX_NULL) + { + + /* Yes, trace is already disabled. */ + status = TX_NOT_DONE; + } + else + { + + /* Otherwise, simply clear the current pointer and registery start pointer to disable the trace. */ + _tx_trace_buffer_current_ptr = TX_NULL; + _tx_trace_registry_start_ptr = TX_NULL; + + /* Successful completion. */ + status = TX_SUCCESS; + } + + /* Return completion status. */ + return(status); + +#else + + /* Trace not enabled, return an error. */ + return(TX_FEATURE_NOT_ENABLED); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_enable.c b/3rd_party/threadx/common/src/tx_trace_enable.c new file mode 100644 index 00000000..b325bac0 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_enable.c @@ -0,0 +1,444 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_event_flags.h" +#include "tx_queue.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#endif +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_enable PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the ThreadX trace buffer and the */ +/* associated control variables, enabling it for operation. */ +/* */ +/* INPUT */ +/* */ +/* trace_buffer_start Start of trace buffer */ +/* trace_buffer_size Size (bytes) of trace buffer */ +/* registry_entries Number of object registry */ +/* entries. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_trace_object_register Register existing objects */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_enable(VOID *trace_buffer_start, ULONG trace_buffer_size, ULONG registry_entries) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *thread_ptr; +TX_TIMER *timer_ptr; +TX_EVENT_FLAGS_GROUP *event_flags_ptr; +TX_QUEUE *queue_ptr; +TX_SEMAPHORE *semaphore_ptr; +TX_MUTEX *mutex_ptr; +TX_BLOCK_POOL *block_pool_ptr; +TX_BYTE_POOL *byte_pool_ptr; +UCHAR *work_ptr; +UCHAR *event_start_ptr; +TX_TRACE_OBJECT_ENTRY *entry_ptr; +TX_TRACE_BUFFER_ENTRY *event_ptr; +ULONG i; +UINT status; + + + /* First, see if there is enough room for the control header, the registry entries, and at least one event in + memory supplied to this call. */ + if (trace_buffer_size < ((sizeof(TX_TRACE_HEADER)) + ((sizeof(TX_TRACE_OBJECT_ENTRY)) * registry_entries) + (sizeof(TX_TRACE_BUFFER_ENTRY)))) + { + + /* No, the memory isn't big enough to hold one trace buffer entry. Return an error. */ + status = TX_SIZE_ERROR; + } + + /* Determine if trace is already enabled. */ + else if (_tx_trace_buffer_current_ptr != TX_NULL) + { + + /* Yes, trace is already enabled. */ + status = TX_NOT_DONE; + } + else + { + + /* Set the enable bits for all events enabled. */ + _tx_trace_event_enable_bits = 0xFFFFFFFFUL; + + /* Setup working pointer to the supplied memory. */ + work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(trace_buffer_start); + + /* Setup pointer to the trace control area. */ + _tx_trace_header_ptr = TX_UCHAR_TO_HEADER_POINTER_CONVERT(work_ptr); + + /* Move the working pointer past the control area. */ + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_HEADER))); + + /* Save the start of the trace object registry. */ + _tx_trace_registry_start_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + /* Setup the end of the trace object registry. */ + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_OBJECT_ENTRY))*registry_entries); + _tx_trace_registry_end_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + /* Loop to make all trace object registry entries empty and valid. */ + for (i = ((ULONG) 0); i < registry_entries; i++) + { + + /* Setup the work pointer. */ + work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(TX_TRACE_OBJECT_ENTRY))*i); + + /* Convert to a registry entry pointer. */ + entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + /* Initialize object registry entry. */ + entry_ptr -> tx_trace_object_entry_available = (UCHAR) TX_TRUE; + entry_ptr -> tx_trace_object_entry_type = (UCHAR) TX_TRACE_OBJECT_TYPE_NOT_VALID; + entry_ptr -> tx_trace_object_entry_reserved1 = (UCHAR) 0; + entry_ptr -> tx_trace_object_entry_reserved2 = (UCHAR) 0; + entry_ptr -> tx_trace_object_entry_thread_pointer = (ULONG) 0; + } + + /* Setup the total number of registry entries. */ + _tx_trace_total_registry_entries = registry_entries; + + /* Setup the object registry available count to the total number of registry entries. */ + _tx_trace_available_registry_entries = registry_entries; + + /* Setup the search starting index to the first entry. */ + _tx_trace_registry_search_start = ((ULONG) 0); + + /* Setup the work pointer to after the trace object registry. */ + work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_end_ptr); + + /* Adjust the remaining trace buffer size. */ + trace_buffer_size = trace_buffer_size - ((sizeof(TX_TRACE_OBJECT_ENTRY)) * registry_entries) - (sizeof(TX_TRACE_HEADER)); + + /* Setup pointer to the start of the actual event trace log. */ + _tx_trace_buffer_start_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr); + + /* Save the event trace log start address. */ + event_start_ptr = work_ptr; + + /* Calculate the end of the trace buffer. */ + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((trace_buffer_size/(sizeof(TX_TRACE_BUFFER_ENTRY)))*(sizeof(TX_TRACE_BUFFER_ENTRY)))); + _tx_trace_buffer_end_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr); + + /* Loop to mark all entries in the trace buffer as invalid. */ + for (i = ((ULONG) 0); i < (trace_buffer_size/(sizeof(TX_TRACE_BUFFER_ENTRY))); i++) + { + + /* Setup the work pointer. */ + work_ptr = TX_UCHAR_POINTER_ADD(event_start_ptr, (sizeof(TX_TRACE_BUFFER_ENTRY))*i); + + /* Convert to a trace event pointer. */ + event_ptr = TX_UCHAR_TO_ENTRY_POINTER_CONVERT(work_ptr); + + /* Mark this trace event as invalid. */ + event_ptr -> tx_trace_buffer_entry_thread_pointer = ((ULONG) 0); + } + + /* Now, fill in the event trace control header. */ + _tx_trace_header_ptr -> tx_trace_header_id = TX_TRACE_VALID; + _tx_trace_header_ptr -> tx_trace_header_timer_valid_mask = TX_TRACE_TIME_MASK; + _tx_trace_header_ptr -> tx_trace_header_trace_base_address = TX_POINTER_TO_ULONG_CONVERT(trace_buffer_start); + _tx_trace_header_ptr -> tx_trace_header_registry_start_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_registry_start_ptr); + _tx_trace_header_ptr -> tx_trace_header_reserved1 = ((USHORT) 0); + _tx_trace_header_ptr -> tx_trace_header_object_name_size = ((USHORT) TX_TRACE_OBJECT_REGISTRY_NAME); + _tx_trace_header_ptr -> tx_trace_header_registry_end_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_registry_end_ptr); + _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_start_ptr); + _tx_trace_header_ptr -> tx_trace_header_buffer_end_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_end_ptr); + _tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = TX_POINTER_TO_ULONG_CONVERT(_tx_trace_buffer_start_ptr); + _tx_trace_header_ptr -> tx_trace_header_reserved2 = 0xAAAAAAAAUL; + _tx_trace_header_ptr -> tx_trace_header_reserved3 = 0xBBBBBBBBUL; + _tx_trace_header_ptr -> tx_trace_header_reserved4 = 0xCCCCCCCCUL; + + /* Now, loop through all existing ThreadX objects and register them in the newly setup trace buffer. */ + + /* Disable interrupts. */ + TX_DISABLE + + /* First, disable preemption. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Pickup the first thread and the number of created threads. */ + thread_ptr = _tx_thread_created_ptr; + i = _tx_thread_created_count; + + /* Loop to register all threads. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this thread. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, thread_ptr -> tx_thread_name, + TX_POINTER_TO_ULONG_CONVERT(thread_ptr -> tx_thread_stack_start), (ULONG) thread_ptr -> tx_thread_stack_size); + + /* Move to the next thread. */ + thread_ptr = thread_ptr -> tx_thread_created_next; + } + + /* Pickup the first timer and the number of created timers. */ + timer_ptr = _tx_timer_created_ptr; + i = _tx_timer_created_count; + + /* Loop to register all timers. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this timer. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_TIMER, timer_ptr, timer_ptr -> tx_timer_name, + ((ULONG) 0), timer_ptr -> tx_timer_internal.tx_timer_internal_re_initialize_ticks); + + /* Move to the next timer. */ + timer_ptr = timer_ptr -> tx_timer_created_next; + } + + + /* Pickup the first event flag group and the number of created groups. */ + event_flags_ptr = _tx_event_flags_created_ptr; + i = _tx_event_flags_created_count; + + /* Loop to register all event flags groups. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this event flags group. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, event_flags_ptr, event_flags_ptr -> tx_event_flags_group_name, ((ULONG) 0), ((ULONG) 0)); + + /* Move to the next event flags group. */ + event_flags_ptr = event_flags_ptr -> tx_event_flags_group_created_next; + } + + /* Pickup the first queue and the number of created queues. */ + queue_ptr = _tx_queue_created_ptr; + i = _tx_queue_created_count; + + /* Loop to register all queues. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this queue. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, queue_ptr -> tx_queue_name, + (queue_ptr -> tx_queue_capacity * (sizeof(ULONG))), ((ULONG) 0)); + + /* Move to the next queue. */ + queue_ptr = queue_ptr -> tx_queue_created_next; + } + + /* Pickup the first semaphore and the number of created semaphores. */ + semaphore_ptr = _tx_semaphore_created_ptr; + i = _tx_semaphore_created_count; + + /* Loop to register all semaphores. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this semaphore. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, semaphore_ptr -> tx_semaphore_name, ((ULONG) 0), ((ULONG) 0)); + + /* Move to the next semaphore. */ + semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next; + } + + /* Pickup the first mutex and the number of created mutexes. */ + mutex_ptr = _tx_mutex_created_ptr; + i = _tx_mutex_created_count; + + /* Loop to register all mutexes. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this mutex. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, mutex_ptr -> tx_mutex_name, + (ULONG) mutex_ptr -> tx_mutex_inherit, ((ULONG) 0)); + + /* Move to the next mutex. */ + mutex_ptr = mutex_ptr -> tx_mutex_created_next; + } + + /* Pickup the first block pool and the number of created block pools. */ + block_pool_ptr = _tx_block_pool_created_ptr; + i = _tx_block_pool_created_count; + + /* Loop to register all block pools. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this block pool. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, block_pool_ptr, block_pool_ptr -> tx_block_pool_name, + block_pool_ptr -> tx_block_pool_size, ((ULONG) 0)); + + /* Move to the next block pool. */ + block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next; + } + + /* Pickup the first byte pool and the number of created byte pools. */ + byte_pool_ptr = _tx_byte_pool_created_ptr; + i = _tx_byte_pool_created_count; + + /* Loop to register all byte pools. */ + while (i != ((ULONG) 0)) + { + + /* Decrement the counter. */ + i--; + + /* Register this byte pool. */ + _tx_trace_object_register(TX_TRACE_OBJECT_TYPE_BYTE_POOL, byte_pool_ptr, byte_pool_ptr -> tx_byte_pool_name, + byte_pool_ptr -> tx_byte_pool_size, ((ULONG) 0)); + + /* Move to the next byte pool. */ + byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next; + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Release the preeemption. */ + _tx_thread_preempt_disable--; + + /* Finally, setup the current buffer pointer, which effectively enables the trace! */ + _tx_trace_buffer_current_ptr = (TX_TRACE_BUFFER_ENTRY *) _tx_trace_buffer_start_ptr; + + /* Insert two RUNNING events so the buffer is not empty. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_RUNNING, 0, 0, 0, 0, TX_TRACE_INTERNAL_EVENTS) + TX_TRACE_IN_LINE_INSERT(TX_TRACE_RUNNING, 0, 0, 0, 0, TX_TRACE_INTERNAL_EVENTS) + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* Return successful completion. */ + status = TX_SUCCESS; + } + + /* Return completion status. */ + return(status); +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (trace_buffer_start != TX_NULL) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (trace_buffer_size == ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (registry_entries == ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + + + diff --git a/3rd_party/threadx/common/src/tx_trace_event_filter.c b/3rd_party/threadx/common/src/tx_trace_event_filter.c new file mode 100644 index 00000000..ed97f8a3 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_event_filter.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef TX_SOURCE_CODE +#define TX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_event_filter PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets up the event filter, which allows the */ +/* application to filter various trace events during run-time. */ +/* */ +/* INPUT */ +/* */ +/* event_filter_bits Trace filter event bit(s) */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_event_filter(ULONG event_filter_bits) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Apply the specified filter by clearing the enable bits. */ + _tx_trace_event_enable_bits = _tx_trace_event_enable_bits & (~event_filter_bits); + + /* Return success. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (event_filter_bits != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_event_unfilter.c b/3rd_party/threadx/common/src/tx_trace_event_unfilter.c new file mode 100644 index 00000000..f65690ec --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_event_unfilter.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef TX_SOURCE_CODE +#define TX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_event_unfilter PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function removes the event filter, which allows the */ +/* application to un-filter various trace events during run-time. */ +/* */ +/* INPUT */ +/* */ +/* event_unfilter_bits Trace un-filter event bit(s) */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_event_unfilter(ULONG event_unfilter_bits) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + + /* Make sure the specified bits are set in the event enable variable. */ + _tx_trace_event_enable_bits = _tx_trace_event_enable_bits | event_unfilter_bits; + + /* Return success. */ + return(TX_SUCCESS); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (event_unfilter_bits != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_initialize.c b/3rd_party/threadx/common/src/tx_trace_initialize.c new file mode 100644 index 00000000..d904740a --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_initialize.c @@ -0,0 +1,154 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#ifdef TX_ENABLE_EVENT_TRACE + + +/* Define the pointer to the start of the trace buffer control structure. */ + +TX_TRACE_HEADER *_tx_trace_header_ptr; + + +/* Define the pointer to the start of the trace object registry area in the trace buffer. */ + +TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_start_ptr; + + +/* Define the pointer to the end of the trace object registry area in the trace buffer. */ + +TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_end_ptr; + + +/* Define the pointer to the starting entry of the actual trace event area of the trace buffer. */ + +TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_start_ptr; + + +/* Define the pointer to the ending entry of the actual trace event area of the trace buffer. */ + +TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_end_ptr; + + +/* Define the pointer to the current entry of the actual trace event area of the trace buffer. */ + +TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_current_ptr; + + +/* Define the trace event enable bits, where each bit represents a type of event that can be enabled + or disabled dynamically by the application. */ + +ULONG _tx_trace_event_enable_bits; + + +/* Define a counter that is used in environments that don't have a timer source. This counter + is incremented on each use giving each event a unique timestamp. */ + +ULONG _tx_trace_simulated_time; + + +/* Define the function pointer used to call the application when the trace buffer wraps. If NULL, + the application has not registered a callback function. */ + +VOID (*_tx_trace_full_notify_function)(VOID *buffer); + + +/* Define the total number of registry entries. */ + +ULONG _tx_trace_total_registry_entries; + + +/* Define a counter that is used to track the number of available registry entries. */ + +ULONG _tx_trace_available_registry_entries; + + +/* Define an index that represents the start of the registry search. */ + +ULONG _tx_trace_registry_search_start; + +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the trace component. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_high_level High level initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_trace_initialize(VOID) +{ + +#ifdef TX_ENABLE_EVENT_TRACE +#ifndef TX_DISABLE_REDUNDANT_CLEARING + + /* Initialize all the pointers to the trace buffer to NULL. */ + _tx_trace_header_ptr = TX_NULL; + _tx_trace_registry_start_ptr = TX_NULL; + _tx_trace_registry_end_ptr = TX_NULL; + _tx_trace_buffer_start_ptr = TX_NULL; + _tx_trace_buffer_end_ptr = TX_NULL; + _tx_trace_buffer_current_ptr = TX_NULL; +#endif +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_interrupt_control.c b/3rd_party/threadx/common/src/tx_trace_interrupt_control.c new file mode 100644 index 00000000..d3020e67 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_interrupt_control.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_interrupt_control PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function provides a shell for the tx_interrupt_control */ +/* function so that a trace event can be logged for its use. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt posture */ +/* */ +/* OUTPUT */ +/* */ +/* Previous Interrupt Posture */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_interrupt_control Interrupt control service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_interrupt_control(UINT new_posture) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + +TX_INTERRUPT_SAVE_AREA +UINT saved_posture; + + /* Disable interrupts. */ + TX_DISABLE + + /* Insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(TX_TRACE_INTERRUPT_CONTROL, TX_ULONG_TO_POINTER_CONVERT(new_posture), TX_POINTER_TO_ULONG_CONVERT(&saved_posture), 0, 0, TX_TRACE_INTERRUPT_CONTROL_EVENT) + + /* Restore interrupts. */ + TX_RESTORE + + /* Perform the interrupt service. */ + saved_posture = _tx_thread_interrupt_control(new_posture); + + /* Return saved posture. */ + return(saved_posture); +#else + +UINT saved_posture; + + /* Perform the interrupt service. */ + saved_posture = _tx_thread_interrupt_control(new_posture); + + /* Return saved posture. */ + return(saved_posture); +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_isr_enter_insert.c b/3rd_party/threadx/common/src/tx_trace_isr_enter_insert.c new file mode 100644 index 00000000..fa29b750 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_isr_enter_insert.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_thread.h" +#endif +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_isr_enter_insert PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function provides inserts an ISR entry event into the trace */ +/* buffer. */ +/* */ +/* INPUT */ +/* */ +/* isr_id User defined ISR ID */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_trace_isr_enter_insert(ULONG isr_id) +{ + +TX_INTERRUPT_SAVE_AREA + + +#ifdef TX_ENABLE_EVENT_TRACE + +UINT stack_address; +ULONG system_state; +UINT preempt_disable; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Insert this event into the trace buffer. */ + system_state = TX_THREAD_GET_SYSTEM_STATE(); + preempt_disable = _tx_thread_preempt_disable; + TX_TRACE_IN_LINE_INSERT(TX_TRACE_ISR_ENTER, &stack_address, isr_id, system_state, preempt_disable, TX_TRACE_INTERNAL_EVENTS) + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (isr_id != ((ULONG) 0)) + { + + /* NOP code. */ + TX_DISABLE + TX_RESTORE + } +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_isr_exit_insert.c b/3rd_party/threadx/common/src/tx_trace_isr_exit_insert.c new file mode 100644 index 00000000..ff0ec6c8 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_isr_exit_insert.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#ifdef TX_ENABLE_EVENT_TRACE +#include "tx_thread.h" +#endif +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_isr_exit_insert PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function provides inserts an ISR exit event into the trace */ +/* buffer. */ +/* */ +/* INPUT */ +/* */ +/* isr_id User defined ISR ID */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_trace_isr_exit_insert(ULONG isr_id) +{ + +TX_INTERRUPT_SAVE_AREA + + +#ifdef TX_ENABLE_EVENT_TRACE + +UINT stack_address; +ULONG system_state; +UINT preempt_disable; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Insert this event into the trace buffer. */ + system_state = TX_THREAD_GET_SYSTEM_STATE(); + preempt_disable = _tx_thread_preempt_disable; + TX_TRACE_IN_LINE_INSERT(TX_TRACE_ISR_EXIT, &stack_address, isr_id, system_state, preempt_disable, TX_TRACE_INTERNAL_EVENTS) + + /* Restore interrupts. */ + TX_RESTORE +#else + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (isr_id != ((ULONG) 0)) + { + + /* NOP code. */ + TX_DISABLE + TX_RESTORE + } +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_object_register.c b/3rd_party/threadx/common/src/tx_trace_object_register.c new file mode 100644 index 00000000..da2dafcf --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_object_register.c @@ -0,0 +1,293 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_object_register PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a ThreadX system object in the trace */ +/* registry area. This provides a mapping between the object pointers */ +/* stored in each trace event to the actual ThreadX objects. */ +/* */ +/* INPUT */ +/* */ +/* object_type Type of system object */ +/* object_ptr Address of system object */ +/* object_name Name of system object */ +/* parameter_1 Supplemental parameter 1 */ +/* parameter_2 Supplemental parameter 2 */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + +UINT i, entries; +UINT found, loop_break; +TX_THREAD *thread_ptr; +UCHAR *work_ptr; +TX_TRACE_OBJECT_ENTRY *entry_ptr; + + + /* Determine if the registry area is setup. */ + if (_tx_trace_registry_start_ptr != TX_NULL) + { + + /* Trace buffer is enabled, proceed. */ + + /* Pickup the total entries. */ + entries = _tx_trace_total_registry_entries; + + /* Determine if there are available entries in the registry. */ + if (_tx_trace_available_registry_entries != ((ULONG) 0)) + { + + /* There are more available entries, proceed. */ + + /* Initialize found to the max entries... indicating no space was found. */ + found = entries; + loop_break = TX_FALSE; + + /* Loop to find available entry. */ + i = _tx_trace_registry_search_start; + do + { + + /* Setup the registry entry pointer. */ + work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*i)); + entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + /* Determine if this is the first pass building the registry. A NULL object value indicates this part + of the registry has never been used. */ + if (entry_ptr -> tx_trace_object_entry_thread_pointer == (ULONG) 0) + { + + /* Set found to this index and break out of the loop. */ + found = i; + loop_break = TX_TRUE; + } + + /* Determine if this entry matches the object pointer... we must reuse old entries left in the + registry. */ + if (entry_ptr -> tx_trace_object_entry_thread_pointer == TX_POINTER_TO_ULONG_CONVERT(object_ptr)) + { + + /* Set found to this index and break out of the loop. */ + found = i; + loop_break = TX_TRUE; + } + + /* Determine if we should break out of the loop. */ + if (loop_break == TX_TRUE) + { + + /* Yes, break out of the loop. */ + break; + } + + /* Is this entry available? */ + if (entry_ptr -> tx_trace_object_entry_available == TX_TRUE) + { + + /* Yes, determine if we have not already found an empty slot. */ + if (found == entries) + { + found = i; + } + else + { + + /* Setup a pointer to the found entry. */ + work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*found)); + entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + if (entry_ptr -> tx_trace_object_entry_type != ((UCHAR) 0)) + { + found = i; + } + } + } + + /* Move to the next entry. */ + i++; + + /* Determine if we have wrapped the list. */ + if (i >= entries) + { + + /* Yes, wrap to the beginning of the list. */ + i = ((ULONG) 0); + } + + } while (i != _tx_trace_registry_search_start); + + /* Now determine if an empty or reuse entry has been found. */ + if (found < entries) + { + + /* Decrement the number of available entries. */ + _tx_trace_available_registry_entries--; + + /* Adjust the search index to the next entry. */ + if ((found + ((ULONG) 1)) < entries) + { + + /* Start searching from the next index. */ + _tx_trace_registry_search_start = found + ((ULONG) 1); + } + else + { + + /* Reset the search to the beginning of the list. */ + _tx_trace_registry_search_start = ((ULONG) 0); + } + + /* Yes, an entry has been found... */ + + /* Build a pointer to the found entry. */ + work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*found)); + entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + /* Populate the found entry! */ + entry_ptr -> tx_trace_object_entry_available = ((UCHAR) TX_FALSE); + entry_ptr -> tx_trace_object_entry_type = object_type; + entry_ptr -> tx_trace_object_entry_thread_pointer = TX_POINTER_TO_ULONG_CONVERT(object_ptr); + entry_ptr -> tx_trace_object_entry_param_1 = parameter_1; + entry_ptr -> tx_trace_object_entry_param_2 = parameter_2; + + /* Loop to copy the object name string... */ + for (i = ((ULONG) 0); i < (((ULONG) TX_TRACE_OBJECT_REGISTRY_NAME)-((ULONG) 1)); i++) + { + + /* Setup work pointer to the object name character. */ + work_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, i); + + /* Copy a character of the name. */ + entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *work_ptr; + + /* Determine if we are at the end. */ + if (*work_ptr == ((UCHAR) 0)) + { + break; + } + } + + /* Null terminate the object string. */ + entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) 0; + + /* Determine if a thread object type is present. */ + if (object_type == TX_TRACE_OBJECT_TYPE_THREAD) + { + + /* Yes, a thread object is present. */ + + /* Setup a pointer to the thread. */ + thread_ptr = TX_VOID_TO_THREAD_POINTER_CONVERT(object_ptr); + + /* Store the thread's priority in the reserved bits. */ + entry_ptr -> tx_trace_object_entry_reserved1 = ((UCHAR) 0x80) | ((UCHAR) (thread_ptr -> tx_thread_priority >> ((UCHAR) 8))); + entry_ptr -> tx_trace_object_entry_reserved2 = (UCHAR) (thread_ptr -> tx_thread_priority & ((UCHAR) 0xFF)); + } + else + { + + /* For all other objects, set the reserved bytes to 0. */ + entry_ptr -> tx_trace_object_entry_reserved1 = ((UCHAR) 0); + entry_ptr -> tx_trace_object_entry_reserved2 = ((UCHAR) 0); + } + } + } + } +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (object_type != ((UCHAR) 0)) + { + + if (object_ptr != TX_NULL) + { + + if (object_name != TX_NULL) + { + + if (parameter_1 != ((ULONG) 0)) + { + + if (parameter_2 != ((ULONG) 0)) + { + + /* NOP code. */ + TX_DISABLE + TX_RESTORE + } + } + } + } + } +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_object_unregister.c b/3rd_party/threadx/common/src/tx_trace_object_unregister.c new file mode 100644 index 00000000..5c1bc7d2 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_object_unregister.c @@ -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 */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_object_unregister PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unregisters a ThreadX system object from the trace */ +/* registry area. */ +/* */ +/* INPUT */ +/* */ +/* object_pointer Address of system object */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _tx_trace_object_unregister(VOID *object_ptr) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + +UINT i, entries; +UCHAR *work_ptr; +TX_TRACE_OBJECT_ENTRY *entry_ptr; + + + /* Determine if the registry area is setup. */ + if (_tx_trace_registry_start_ptr != TX_NULL) + { + + /* Registry is setup, proceed. */ + + /* Pickup the total entries. */ + entries = _tx_trace_total_registry_entries; + + /* Loop to find available entry. */ + for (i = ((ULONG) 0); i < entries; i++) + { + + /* Setup the registry entry pointer. */ + work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*i)); + entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr); + + /* Determine if this entry matches the object pointer... */ + if (entry_ptr -> tx_trace_object_entry_thread_pointer == TX_POINTER_TO_ULONG_CONVERT(object_ptr)) + { + + /* Mark this entry as available, but leave the other information so that old trace entries can + still find it - if necessary! */ + entry_ptr -> tx_trace_object_entry_available = ((UCHAR) TX_TRUE); + + /* Increment the number of available registry entries. */ + _tx_trace_available_registry_entries++; + + /* Adjust the search index to this position. */ + _tx_trace_registry_search_start = i; + + break; + } + } + } +#else + +TX_INTERRUPT_SAVE_AREA + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (object_ptr != TX_NULL) + { + + /* NOP code. */ + TX_DISABLE + TX_RESTORE + } +#endif +} + diff --git a/3rd_party/threadx/common/src/tx_trace_user_event_insert.c b/3rd_party/threadx/common/src/tx_trace_user_event_insert.c new file mode 100644 index 00000000..6d0b4004 --- /dev/null +++ b/3rd_party/threadx/common/src/tx_trace_user_event_insert.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_trace.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_trace_user_event_insert PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function inserts a user-defined event into the trace buffer. */ +/* */ +/* INPUT */ +/* */ +/* event_id User Event ID */ +/* info_field_1 First information field */ +/* info_field_2 First information field */ +/* info_field_3 First information field */ +/* info_field_4 First information field */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _tx_trace_user_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4) +{ + +#ifdef TX_ENABLE_EVENT_TRACE + +TX_INTERRUPT_SAVE_AREA + +UINT status; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if trace is disabled. */ + if (_tx_trace_buffer_current_ptr == TX_NULL) + { + + /* Yes, trace is already disabled. */ + status = TX_NOT_DONE; + } + else + { + + /* Insert this event into the trace buffer. */ +#ifdef TX_MISRA_ENABLE + TX_TRACE_IN_LINE_INSERT(event_id, TX_ULONG_TO_POINTER_CONVERT(info_field_1), info_field_2, info_field_3, info_field_4, ((ULONG) TX_TRACE_USER_EVENTS)) +#else + TX_TRACE_IN_LINE_INSERT(event_id, info_field_1, info_field_2, info_field_3, info_field_4, TX_TRACE_USER_EVENTS) +#endif + + /* Return successful status. */ + status = TX_SUCCESS; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(status); + +#else + +UINT status; + + + /* Access input arguments just for the sake of lint, MISRA, etc. */ + if (event_id != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (info_field_1 != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (info_field_2 != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (info_field_3 != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else if (info_field_4 != ((ULONG) 0)) + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + else + { + + /* Trace not enabled, return an error. */ + status = TX_FEATURE_NOT_ENABLED; + } + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/3rd_party/threadx/common/src/txe_block_allocate.c b/3rd_party/threadx/common/src/txe_block_allocate.c new file mode 100644 index 00000000..cf4c2ed4 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_block_allocate.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_block_allocate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the allocate block memory */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* block_ptr Pointer to place allocated block */ +/* pointer */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid pool pointer */ +/* TX_PTR_ERROR Invalid destination pointer */ +/* TX_WAIT_ERROR Invalid wait option */ +/* status Actual Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_allocate Actual block allocate function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option) +{ + +UINT status; + +#ifndef TX_TIMER_PROCESS_IN_ISR + +TX_THREAD *current_thread; +#endif + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for an invalid pool pointer. */ + else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for an invalid destination for return pointer. */ + else if (block_ptr == TX_NULL) + { + + /* Null destination pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual block allocate function. */ + status = _tx_block_allocate(pool_ptr, block_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_block_pool_create.c b/3rd_party/threadx/common/src/txe_block_pool_create.c new file mode 100644 index 00000000..d964f1cb --- /dev/null +++ b/3rd_party/threadx/common/src/txe_block_pool_create.c @@ -0,0 +1,229 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_block_pool_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the create block memory pool */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* name_ptr Pointer to block pool name */ +/* block_size Number of bytes in each block */ +/* pool_start Address of beginning of pool area */ +/* pool_size Number of bytes in the block pool */ +/* pool_control_block_size Size of block pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid pool pointer */ +/* TX_PTR_ERROR Invalid starting address */ +/* TX_SIZE_ERROR Invalid pool size */ +/* TX_CALLER_ERROR Invalid caller of pool */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_pool_create Actual block pool create function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, + VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_BLOCK_POOL *next_pool; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for invalid control block size. */ + else if (pool_control_block_size != (sizeof(TX_BLOCK_POOL))) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_pool = _tx_block_pool_created_ptr; + for (i = ((ULONG) 0); i < _tx_block_pool_created_count; i++) + { + + /* Determine if this block pool matches the pool in the list. */ + if (pool_ptr == next_pool) + { + + break; + } + else + { + /* Move to the next pool. */ + next_pool = next_pool -> tx_block_pool_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate pool. */ + if (pool_ptr == next_pool) + { + + /* Pool is already created, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for an invalid starting address. */ + else if (pool_start == TX_NULL) + { + + /* Null starting address pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Check for invalid pool size. */ + if ((((block_size/(sizeof(void *)))*(sizeof(void *))) + (sizeof(void *))) > + ((pool_size/(sizeof(void *)))*(sizeof(void *)))) + { + + /* Not enough memory for one block, return appropriate error. */ + status = TX_SIZE_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual block pool create function. */ + status = _tx_block_pool_create(pool_ptr, name_ptr, block_size, pool_start, pool_size); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_block_pool_delete.c b/3rd_party/threadx/common/src/txe_block_pool_delete.c new file mode 100644 index 00000000..2ee152b9 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_block_pool_delete.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_block_pool_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the delete block pool memory */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid memory block pool pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual delete function status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_pool_delete Actual block pool delete function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_block_pool_delete(TX_BLOCK_POOL *pool_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Default status to success. */ + status = TX_SUCCESS; +#endif + + /* Check for an invalid pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check the pool ID. */ + else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for invalid caller of this function. */ + + /* Is the call from an ISR or initialization? */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Is the call from the system timer thread? */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { +#endif + + /* Call actual block pool delete function. */ + status = _tx_block_pool_delete(pool_ptr); + +#ifndef TX_TIMER_PROCESS_IN_ISR + } +#endif + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_block_pool_info_get.c b/3rd_party/threadx/common/src/txe_block_pool_info_get.c new file mode 100644 index 00000000..ecd544c4 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_block_pool_info_get.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_block_pool_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the block pool information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to block pool control blk */ +/* name Destination for the pool name */ +/* available_blocks Number of free blocks in pool */ +/* total_blocks Total number of blocks in pool */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on block pool */ +/* suspended_count Destination for suspended count */ +/* next_pool Destination for pointer to next */ +/* block pool on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid block pool pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_pool_info_get Actual block pool info get service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, + ULONG *total_blocks, TX_THREAD **first_suspended, + ULONG *suspended_count, TX_BLOCK_POOL **next_pool) +{ + + +UINT status; + + + /* Check for an invalid block pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Block pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check the pool ID. */ + else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) + { + + /* Block pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + else + { + + /* Otherwise, call the actual block pool information get service. */ + status = _tx_block_pool_info_get(pool_ptr, name, available_blocks, + total_blocks, first_suspended, suspended_count, next_pool); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_block_pool_prioritize.c b/3rd_party/threadx/common/src/txe_block_pool_prioritize.c new file mode 100644 index 00000000..5d9088d5 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_block_pool_prioritize.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_block_pool_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the block pool prioritize call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_pool_prioritize Actual block pool prioritize */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr) +{ + +UINT status; + + + /* Check for an invalid block memory pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Block memory pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check for invalid pool ID. */ + else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) + { + + /* Block memory pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + else + { + + /* Call actual block pool prioritize function. */ + status = _tx_block_pool_prioritize(pool_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_block_release.c b/3rd_party/threadx/common/src/txe_block_release.c new file mode 100644 index 00000000..7c4ca6aa --- /dev/null +++ b/3rd_party/threadx/common/src/txe_block_release.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Block Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_block_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_block_release PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the block release function call. */ +/* */ +/* INPUT */ +/* */ +/* block_ptr Pointer to memory block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_PTR_ERROR Invalid memory block pointer */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_block_release Actual block release function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_block_release(VOID *block_ptr) +{ + +UINT status; +TX_BLOCK_POOL *pool_ptr; +UCHAR **indirect_ptr; +UCHAR *work_ptr; + + + /* First check the supplied pointer. */ + if (block_ptr == TX_NULL) + { + + /* The block pointer is invalid, return appropriate status. */ + status = TX_PTR_ERROR; + } + else + { + + /* Pickup the pool pointer which is just previous to the starting + address of block that the caller sees. */ + work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr); + work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *))); + indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr); + work_ptr = *indirect_ptr; + pool_ptr = TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT(work_ptr); + + /* Check for an invalid pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_PTR_ERROR; + } + + /* Now check for invalid pool ID. */ + else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID) + { + + /* Pool pointer is invalid, return appropriate error code. */ + status = TX_PTR_ERROR; + } + else + { + + /* Call actual block release function. */ + status = _tx_block_release(block_ptr); + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_byte_allocate.c b/3rd_party/threadx/common/src/txe_byte_allocate.c new file mode 100644 index 00000000..7c522bae --- /dev/null +++ b/3rd_party/threadx/common/src/txe_byte_allocate.c @@ -0,0 +1,201 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_byte_allocate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in allocate bytes function call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* memory_ptr Pointer to place allocated bytes */ +/* pointer */ +/* memory_size Number of bytes to allocate */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid memory pool pointer */ +/* TX_PTR_ERROR Invalid destination pointer */ +/* TX_WAIT_ERROR Invalid wait option */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* TX_SIZE_ERROR Invalid size of memory request */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_allocate Actual byte allocate function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, + ULONG memory_size, ULONG wait_option) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid byte pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check for invalid pool ID. */ + else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for an invalid destination for return pointer. */ + else if (memory_ptr == TX_NULL) + { + + /* Null destination pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + + /* Check for an invalid memory size. */ + else if (memory_size == ((ULONG) 0)) + { + + /* Error in size, return appropriate error. */ + status = TX_SIZE_ERROR; + } + + /* Determine if the size is greater than the pool size. */ + else if (memory_size > pool_ptr -> tx_byte_pool_size) + { + + /* Error in size, return appropriate error. */ + status = TX_SIZE_ERROR; + } + + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is call from ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } + } +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Check for timer execution. */ + if (status == TX_SUCCESS) + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } +#endif + + /* Is everything still okay? */ + if (status == TX_SUCCESS) + { + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual byte memory allocate function. */ + status = _tx_byte_allocate(pool_ptr, memory_ptr, memory_size, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_byte_pool_create.c b/3rd_party/threadx/common/src/txe_byte_pool_create.c new file mode 100644 index 00000000..291a7c74 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_byte_pool_create.c @@ -0,0 +1,224 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_byte_pool_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the create byte pool memory */ +/* function. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* name_ptr Pointer to byte pool name */ +/* pool_start Address of beginning of pool area */ +/* pool_size Number of bytes in the byte pool */ +/* pool_control_block_size Size of byte pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid byte pool pointer */ +/* TX_PTR_ERROR Invalid pool starting address */ +/* TX_SIZE_ERROR Invalid pool size */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_pool_create Actual byte pool create function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_BYTE_POOL *next_pool; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid byte pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now see if the pool control block size is valid. */ + else if (pool_control_block_size != (sizeof(TX_BYTE_POOL))) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_pool = _tx_byte_pool_created_ptr; + for (i = ((ULONG) 0); i < _tx_byte_pool_created_count; i++) + { + + /* Determine if this byte pool matches the pool in the list. */ + if (pool_ptr == next_pool) + { + + break; + } + else + { + + /* Move to the next pool. */ + next_pool = next_pool -> tx_byte_pool_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate pool. */ + if (pool_ptr == next_pool) + { + + /* Pool is already created, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for an invalid starting address. */ + else if (pool_start == TX_NULL) + { + + /* Null starting address pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + + /* Check for invalid pool size. */ + else if (pool_size < TX_BYTE_POOL_MIN) + { + + /* Pool not big enough, return appropriate error. */ + status = TX_SIZE_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual byte pool create function. */ + status = _tx_byte_pool_create(pool_ptr, name_ptr, pool_start, pool_size); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_byte_pool_delete.c b/3rd_party/threadx/common/src/txe_byte_pool_delete.c new file mode 100644 index 00000000..28f33dff --- /dev/null +++ b/3rd_party/threadx/common/src/txe_byte_pool_delete.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Pool */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_byte_pool_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the delete byte pool function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid pool pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_pool_delete Actual byte pool delete function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_byte_pool_delete(TX_BYTE_POOL *pool_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Default status to success. */ + status = TX_SUCCESS; +#endif + + /* Check for an invalid byte pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check the pool ID. */ + else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Check for interrupt or initialization. */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { +#endif + + /* Call actual byte pool delete function. */ + status = _tx_byte_pool_delete(pool_ptr); + +#ifndef TX_TIMER_PROCESS_IN_ISR + } +#endif + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_byte_pool_info_get.c b/3rd_party/threadx/common/src/txe_byte_pool_info_get.c new file mode 100644 index 00000000..69ec38c6 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_byte_pool_info_get.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_byte_pool_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the byte pool information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to byte pool control block*/ +/* name Destination for the pool name */ +/* available_bytes Number of free bytes in byte pool */ +/* fragments Number of fragments in byte pool */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on byte pool */ +/* suspended_count Destination for suspended count */ +/* next_pool Destination for pointer to next */ +/* byte pool on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_POOL_ERROR Invalid byte pool pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_pool_info_get Actual byte pool info get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, + ULONG *fragments, TX_THREAD **first_suspended, + ULONG *suspended_count, TX_BYTE_POOL **next_pool) +{ + +UINT status; + + + /* Check for an invalid byte pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Block pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check for invalid pool ID. */ + else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) + { + + /* Block pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + else + { + + /* Otherwise, call the actual byte pool information get service. */ + status = _tx_byte_pool_info_get(pool_ptr, name, available_bytes, + fragments, first_suspended, suspended_count, next_pool); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_byte_pool_prioritize.c b/3rd_party/threadx/common/src/txe_byte_pool_prioritize.c new file mode 100644 index 00000000..3a09dd37 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_byte_pool_prioritize.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_byte_pool_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the byte pool prioritize call. */ +/* */ +/* INPUT */ +/* */ +/* pool_ptr Pointer to pool control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_pool_prioritize Actual byte pool prioritize */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr) +{ + +UINT status; + + + /* Check for an invalid byte memory pool pointer. */ + if (pool_ptr == TX_NULL) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + + /* Now check for invalid pool ID. */ + else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) + { + + /* Byte pool pointer is invalid, return appropriate error code. */ + status = TX_POOL_ERROR; + } + else + { + + /* Call actual byte pool prioritize function. */ + status = _tx_byte_pool_prioritize(pool_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_byte_release.c b/3rd_party/threadx/common/src/txe_byte_release.c new file mode 100644 index 00000000..99000210 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_byte_release.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Byte Memory */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_byte_pool.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_byte_release PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the release byte function call. */ +/* */ +/* INPUT */ +/* */ +/* memory_ptr Pointer to allocated memory */ +/* */ +/* OUTPUT */ +/* */ +/* TX_PTR_ERROR Invalid memory pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_release Actual byte release function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* First check the supplied memory pointer. */ + if (memory_ptr == TX_NULL) + { + + /* The byte memory pointer is invalid, return appropriate status. */ + status = TX_PTR_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual byte release function. */ + status = _tx_byte_release(memory_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_event_flags_create.c b/3rd_party/threadx/common/src/txe_event_flags_create.c new file mode 100644 index 00000000..67da058a --- /dev/null +++ b/3rd_party/threadx/common/src/txe_event_flags_create.c @@ -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 */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_event_flags_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the event flag creation function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to event flags group */ +/* control block */ +/* name_ptr Pointer to event flags name */ +/* event_control_block_size Size of event flags control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_GROUP_ERROR Invalid event flag group pointer */ +/* TX_CALLER_ERROR Invalid calling function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_event_flags_create Actual create function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_EVENT_FLAGS_GROUP *next_group; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid event flags group pointer. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Now check for proper control block size. */ + else if (event_control_block_size != (sizeof(TX_EVENT_FLAGS_GROUP))) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_group = _tx_event_flags_created_ptr; + for (i = ((ULONG) 0); i < _tx_event_flags_created_count; i++) + { + + /* Determine if this group matches the event flags group in the list. */ + if (group_ptr == next_group) + { + + break; + } + else + { + + /* Move to the next group. */ + next_group = next_group -> tx_event_flags_group_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate event flag group. */ + if (group_ptr == next_group) + { + + /* Group is already created, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual event flags create function. */ + status = _tx_event_flags_create(group_ptr, name_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_event_flags_delete.c b/3rd_party/threadx/common/src/txe_event_flags_delete.c new file mode 100644 index 00000000..5a4031c8 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_event_flags_delete.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_event_flags_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the delete event flags group */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_GROUP_ERROR Invalid event flag group pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_event_flags_delete Actual delete event flags function*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Default status to success. */ + status = TX_SUCCESS; +#endif + + /* Check for an invalid event flag group pointer. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Now check for invalid event flag group ID. */ + else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Check for invalid caller of this function. */ + + /* Is the caller an ISR or Initialization? */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Is the caller the system timer thread? */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { +#endif + + /* Call actual event flag group delete function. */ + status = _tx_event_flags_delete(group_ptr); + +#ifndef TX_TIMER_PROCESS_IN_ISR + } +#endif + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_event_flags_get.c b/3rd_party/threadx/common/src/txe_event_flags_get.c new file mode 100644 index 00000000..a77b6269 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_event_flags_get.c @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_event_flags_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the event flags get function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block */ +/* requested_event_flags Event flags requested */ +/* get_option Specifies and/or and clear options*/ +/* actual_flags_ptr Pointer to place the actual flags */ +/* the service retrieved */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_GROUP_ERROR Invalid event flags group pointer */ +/* TX_PTR_ERROR Invalid actual flags pointer */ +/* TX_WAIT_ERROR Invalid wait option */ +/* TX_OPTION_ERROR Invalid get option */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_event_flags_get Actual event flags get function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, + UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option) +{ + +UINT status; + +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid event flag group pointer. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Now check for invalid event group ID. */ + else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Check for an invalid destination for actual flags. */ + else if (actual_flags_ptr == TX_NULL) + { + + /* Null destination pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Is everything still okay? */ + if (status == TX_SUCCESS) + { + + /* Check for invalid get option. */ + if (get_option > TX_AND_CLEAR) + { + + /* Invalid get events option, return appropriate error. */ + status = TX_OPTION_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual event flags get function. */ + status = _tx_event_flags_get(group_ptr, requested_flags, get_option, actual_flags_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_event_flags_info_get.c b/3rd_party/threadx/common/src/txe_event_flags_info_get.c new file mode 100644 index 00000000..b5268e2e --- /dev/null +++ b/3rd_party/threadx/common/src/txe_event_flags_info_get.c @@ -0,0 +1,117 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_event_flags_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the event flag information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to event flag group */ +/* name Destination for the event flags */ +/* group name */ +/* current_flags Current event flags */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on event flags */ +/* suspended_count Destination for suspended count */ +/* next_group Destination for pointer to next */ +/* event flag group on the created */ +/* list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_GROUP_ERROR Invalid event flag group pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_event_flags_info_get Actual event flags group info */ +/* get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, + TX_THREAD **first_suspended, ULONG *suspended_count, + TX_EVENT_FLAGS_GROUP **next_group) +{ + +UINT status; + + + /* Check for an invalid event flag group pointer. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Now check for invalid event flag group ID. */ + else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + else + { + + /* Otherwise, call the actual event flags group information get service. */ + status = _tx_event_flags_info_get(group_ptr, name, current_flags, first_suspended, + suspended_count, next_group); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_event_flags_set.c b/3rd_party/threadx/common/src/txe_event_flags_set.c new file mode 100644 index 00000000..81c39955 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_event_flags_set.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_event_flags_set PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the set event flags function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block */ +/* flags_to_set Event flags to set */ +/* set_option Specified either AND or OR */ +/* operation on the event flags */ +/* */ +/* OUTPUT */ +/* */ +/* TX_GROUP_ERROR Invalid event flags group pointer */ +/* TX_OPTION_ERROR Invalid set option */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_event_flags_set Actual set event flags function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option) +{ + +UINT status; + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid event flag group pointer. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Now check for invalid event flag group ID. */ + else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + else + { + + /* Check for invalid set option. */ + if (set_option != TX_AND) + { + + if (set_option != TX_OR) + { + + /* Invalid set events option, return appropriate error. */ + status = TX_OPTION_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual event flags set function. */ + status = _tx_event_flags_set(group_ptr, flags_to_set, set_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_event_flags_set_notify.c b/3rd_party/threadx/common/src/txe_event_flags_set_notify.c new file mode 100644 index 00000000..b0f4357a --- /dev/null +++ b/3rd_party/threadx/common/src/txe_event_flags_set_notify.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Event Flags */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_event_flags.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_event_flags_set_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the event flags set notify */ +/* callback function call. */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Pointer to group control block*/ +/* group_put_notify Application callback function */ +/* (TX_NULL disables notify) */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_event_flags_set_notify Actual event flags set notify */ +/* call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)) +{ + +UINT status; + + + /* Check for an invalid group pointer. */ + if (group_ptr == TX_NULL) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + + /* Now check for invalid event group ID. */ + else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID) + { + + /* Event flags group pointer is invalid, return appropriate error code. */ + status = TX_GROUP_ERROR; + } + else + { + + /* Call actual event flags set notify function. */ + status = _tx_event_flags_set_notify(group_ptr, events_set_notify); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_mutex_create.c b/3rd_party/threadx/common/src/txe_mutex_create.c new file mode 100644 index 00000000..57c104e7 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_mutex_create.c @@ -0,0 +1,223 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_mutex_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the create mutex function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* name_ptr Pointer to mutex name */ +/* inherit Initial mutex count */ +/* mutex_control_block_size Size of mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_MUTEX_ERROR Invalid mutex pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* TX_INHERIT_ERROR Invalid inherit option */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_create Actual create mutex function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_MUTEX *next_mutex; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid mutex pointer. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Now check to make sure the control block is the correct size. */ + else if (mutex_control_block_size != (sizeof(TX_MUTEX))) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_mutex = _tx_mutex_created_ptr; + for (i = ((ULONG) 0); i < _tx_mutex_created_count; i++) + { + + /* Determine if this mutex matches the mutex in the list. */ + if (mutex_ptr == next_mutex) + { + + break; + } + else + { + + /* Move to the next mutex. */ + next_mutex = next_mutex -> tx_mutex_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate mutex. */ + if (mutex_ptr == next_mutex) + { + + /* Mutex is already created, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + else + { + + /* Check for a valid inherit option. */ + if (inherit != TX_INHERIT) + { + + if (inherit != TX_NO_INHERIT) + { + + /* Inherit option is illegal. */ + status = TX_INHERIT_ERROR; + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual mutex create function. */ + status = _tx_mutex_create(mutex_ptr, name_ptr, inherit); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_mutex_delete.c b/3rd_party/threadx/common/src/txe_mutex_delete.c new file mode 100644 index 00000000..0b7ab706 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_mutex_delete.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_mutex_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the mutex delete function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_MUTEX_ERROR Invalid mutex pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_delete Actual delete mutex function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_mutex_delete(TX_MUTEX *mutex_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Default status to success. */ + status = TX_SUCCESS; +#endif + + /* Check for an invalid mutex pointer. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Now check for a valid mutex ID. */ + else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Check for invalid caller of this function. */ + + /* Is the caller an ISR or Initialization? */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Is the caller the system timer thread? */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { +#endif + + /* Call actual mutex delete function. */ + status = _tx_mutex_delete(mutex_ptr); + +#ifndef TX_TIMER_PROCESS_IN_ISR + } +#endif + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_mutex_get.c b/3rd_party/threadx/common/src/txe_mutex_get.c new file mode 100644 index 00000000..dd660009 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_mutex_get.c @@ -0,0 +1,170 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#ifndef TX_TIMER_PROCESS_IN_ISR +#include "tx_timer.h" +#endif +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_mutex_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the mutex get function call. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_MUTEX_ERROR Invalid mutex pointer */ +/* TX_WAIT_ERROR Invalid wait option */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_get Actual get mutex function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid mutex pointer. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Now check for a valid mutex ID. */ + else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Yes, invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual get mutex function. */ + status = _tx_mutex_get(mutex_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_mutex_info_get.c b/3rd_party/threadx/common/src/txe_mutex_info_get.c new file mode 100644 index 00000000..69e3c814 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_mutex_info_get.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_mutex_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the mutex information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* name Destination for the mutex name */ +/* count Destination for the owner count */ +/* owner Destination for the owner's */ +/* thread control block pointer */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on the mutex */ +/* suspended_count Destination for suspended count */ +/* next_mutex Destination for pointer to next */ +/* mutex on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_MUTEX_ERROR Invalid mutex pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_info_get Actual mutex info get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, + TX_THREAD **first_suspended, ULONG *suspended_count, + TX_MUTEX **next_mutex) +{ + +UINT status; + + + /* Check for an invalid mutex pointer. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Now check for invalid mutex ID. */ + else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + else + { + + /* Otherwise, call the actual mutex information get service. */ + status = _tx_mutex_info_get(mutex_ptr, name, count, owner, first_suspended, + suspended_count, next_mutex); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_mutex_prioritize.c b/3rd_party/threadx/common/src/txe_mutex_prioritize.c new file mode 100644 index 00000000..679e3ac8 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_mutex_prioritize.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_mutex_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the mutex prioritize call. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_prioritize Actual mutex prioritize */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_mutex_prioritize(TX_MUTEX *mutex_ptr) +{ + +UINT status; + + + /* Check for an invalid mutex pointer. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Now check for invalid mutex ID. */ + else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + else + { + + /* Call actual mutex prioritize function. */ + status = _tx_mutex_prioritize(mutex_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_mutex_put.c b/3rd_party/threadx/common/src/txe_mutex_put.c new file mode 100644 index 00000000..7a6fdffc --- /dev/null +++ b/3rd_party/threadx/common/src/txe_mutex_put.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Mutex */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_mutex_put PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the mutex put function call. */ +/* */ +/* INPUT */ +/* */ +/* mutex_ptr Pointer to mutex control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_MUTEX_ERROR Invalid mutex pointer */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_put Actual put mutex function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + +UINT status; + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid mutex pointer. */ + if (mutex_ptr == TX_NULL) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + + /* Now check for invalid mutex ID. */ + else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Mutex pointer is invalid, return appropriate error code. */ + status = TX_MUTEX_ERROR; + } + else + { + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual put mutex function. */ + status = _tx_mutex_put(mutex_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_create.c b/3rd_party/threadx/common/src/txe_queue_create.c new file mode 100644 index 00000000..592d0a89 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_create.c @@ -0,0 +1,239 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_timer.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue create function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* name_ptr Pointer to queue name */ +/* message_size Size of each queue message */ +/* queue_start Starting address of the queue area*/ +/* queue_size Number of bytes in the queue */ +/* queue_control_block_size Size of queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* TX_PTR_ERROR Invalid starting address of queue */ +/* TX_SIZE_ERROR Invalid message queue size */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_create Actual queue create function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, + VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_QUEUE *next_queue; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for a valid control block size. */ + else if (queue_control_block_size != (sizeof(TX_QUEUE))) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_queue = _tx_queue_created_ptr; + for (i = ((ULONG) 0); i < _tx_queue_created_count; i++) + { + + /* Determine if this queue matches the queue in the list. */ + if (queue_ptr == next_queue) + { + + break; + } + else + { + + /* Move to the next queue. */ + next_queue = next_queue -> tx_queue_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate queue. */ + if (queue_ptr == next_queue) + { + + /* Queue is already created, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Check the starting address of the queue. */ + else if (queue_start == TX_NULL) + { + + /* Invalid starting address of queue. */ + status = TX_PTR_ERROR; + } + + /* Check for an invalid message size - less than 1. */ + else if (message_size < TX_1_ULONG) + { + + /* Invalid message size specified. */ + status = TX_SIZE_ERROR; + } + + /* Check for an invalid message size - greater than 16. */ + else if (message_size > TX_16_ULONG) + { + + /* Invalid message size specified. */ + status = TX_SIZE_ERROR; + } + + /* Check on the queue size. */ + else if ((queue_size/(sizeof(ULONG))) < message_size) + { + + /* Invalid queue size specified. */ + status = TX_SIZE_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual queue create function. */ + status = _tx_queue_create(queue_ptr, name_ptr, message_size, queue_start, queue_size); + } + + /* Return completion status. */ + return(status); +} diff --git a/3rd_party/threadx/common/src/txe_queue_delete.c b/3rd_party/threadx/common/src/txe_queue_delete.c new file mode 100644 index 00000000..b61b923f --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_delete.c @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue delete function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_delete Actual queue delete function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_delete(TX_QUEUE *queue_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for a valid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + else + { + + /* Check for invalid caller of this function. */ + + /* Is the caller an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Is the caller the system timer thread? */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } +#endif + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual queue delete function. */ + status = _tx_queue_delete(queue_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_flush.c b/3rd_party/threadx/common/src/txe_queue_flush.c new file mode 100644 index 00000000..611b7b51 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_flush.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_flush PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue flush function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_flush Actual queue flush function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_flush(TX_QUEUE *queue_ptr) +{ + +UINT status; + + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for invalid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + else + { + + /* Call actual queue flush function. */ + status = _tx_queue_flush(queue_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_front_send.c b/3rd_party/threadx/common/src/txe_queue_front_send.c new file mode 100644 index 00000000..ae38162f --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_front_send.c @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_front_send PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue send function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* source_ptr Pointer to message source */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* TX_PTR_ERROR Invalid source pointer - NULL */ +/* TX_WAIT_ERROR Invalid wait option - non thread */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_front_send Actual queue send function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) +{ + +UINT status; + +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for invalid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Check for an invalid source for message. */ + else if (source_ptr == TX_NULL) + { + + /* Null source pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual queue front send function. */ + status = _tx_queue_front_send(queue_ptr, source_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_info_get.c b/3rd_party/threadx/common/src/txe_queue_info_get.c new file mode 100644 index 00000000..f60e3d97 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_info_get.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* name Destination for the queue name */ +/* enqueued Destination for enqueued count */ +/* available_storage Destination for available storage */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on this queue */ +/* suspended_count Destination for suspended count */ +/* next_queue Destination for pointer to next */ +/* queue on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_info_get Actual information get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, + TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) +{ + +UINT status; + + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for a valid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + else + { + + /* Otherwise, call the actual queue information get service. */ + status = _tx_queue_info_get(queue_ptr, name, enqueued, available_storage, first_suspended, + suspended_count, next_queue); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_prioritize.c b/3rd_party/threadx/common/src/txe_queue_prioritize.c new file mode 100644 index 00000000..ca91c762 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_prioritize.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue prioritize call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_prioritize Actual queue prioritize function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_prioritize(TX_QUEUE *queue_ptr) +{ + +UINT status; + + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for invalid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + else + { + + /* Call actual queue prioritize function. */ + status = _tx_queue_prioritize(queue_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_receive.c b/3rd_party/threadx/common/src/txe_queue_receive.c new file mode 100644 index 00000000..d00e6b94 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_receive.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_receive PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue receive function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* destination_ptr Pointer to message destination */ +/* **** MUST BE LARGE ENOUGH TO */ +/* HOLD MESSAGE **** */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* TX_PTR_ERROR Invalid destination pointer (NULL)*/ +/* TX_WAIT_ERROR Invalid wait option */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_receive Actual queue receive function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option) +{ + +UINT status; + +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for invalid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Check for an invalid destination for message. */ + else if (destination_ptr == TX_NULL) + { + + /* Null destination pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual queue receive function. */ + status = _tx_queue_receive(queue_ptr, destination_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_send.c b/3rd_party/threadx/common/src/txe_queue_send.c new file mode 100644 index 00000000..03a6f866 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_send.c @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_send PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue send function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block */ +/* source_ptr Pointer to message source */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_QUEUE_ERROR Invalid queue pointer */ +/* TX_PTR_ERROR Invalid source pointer - NULL */ +/* TX_WAIT_ERROR Invalid wait option */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_send Actual queue send function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) +{ + +UINT status; + +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for invalid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Check for an invalid source for message. */ + else if (source_ptr == TX_NULL) + { + + /* Null source pointer, return appropriate error. */ + status = TX_PTR_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual queue send function. */ + status = _tx_queue_send(queue_ptr, source_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_queue_send_notify.c b/3rd_party/threadx/common/src/txe_queue_send_notify.c new file mode 100644 index 00000000..b90ff386 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_queue_send_notify.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Queue */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_queue.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_queue_send_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the queue send notify */ +/* callback function call. */ +/* */ +/* INPUT */ +/* */ +/* queue_ptr Pointer to queue control block*/ +/* queue_send_notify Application callback function */ +/* (TX_NULL disables notify) */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_queue_send_notify Actual queue send notify call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)) +{ + +UINT status; + + + /* Check for an invalid queue pointer. */ + if (queue_ptr == TX_NULL) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + + /* Now check for a valid queue ID. */ + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + + /* Queue pointer is invalid, return appropriate error code. */ + status = TX_QUEUE_ERROR; + } + else + { + + /* Call actual queue send notify function. */ + status = _tx_queue_send_notify(queue_ptr, queue_send_notify); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_ceiling_put.c b/3rd_party/threadx/common/src/txe_semaphore_ceiling_put.c new file mode 100644 index 00000000..7aafcd23 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_ceiling_put.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_ceiling_put PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore ceiling put */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore */ +/* ceiling Maximum value of semaphore */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */ +/* TX_INVALID_CEILING Invalid semaphore ceiling */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_ceiling_put Actual semaphore ceiling put */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling) +{ + +UINT status; + + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for a valid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Determine if the ceiling is valid - must be greater than 1. */ + else if (ceiling == ((ULONG) 0)) + { + + /* Invalid ceiling, return error. */ + status = TX_INVALID_CEILING; + } + else + { + + /* Call actual semaphore ceiling put function. */ + status = _tx_semaphore_ceiling_put(semaphore_ptr, ceiling); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_create.c b/3rd_party/threadx/common/src/txe_semaphore_create.c new file mode 100644 index 00000000..84a047a8 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_create.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the create semaphore function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* name_ptr Pointer to semaphore name */ +/* initial_count Initial semaphore count */ +/* semaphore_control_block_size Size of semaphore control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_create Actual create semaphore function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_SEMAPHORE *next_semaphore; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for a valid semaphore ID. */ + else if (semaphore_control_block_size != (sizeof(TX_SEMAPHORE))) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_semaphore = _tx_semaphore_created_ptr; + for (i = ((ULONG) 0); i < _tx_semaphore_created_count; i++) + { + + /* Determine if this semaphore matches the current semaphore in the list. */ + if (semaphore_ptr == next_semaphore) + { + + break; + } + else + { + + /* Move to next semaphore. */ + next_semaphore = next_semaphore -> tx_semaphore_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate semaphore. */ + if (semaphore_ptr == next_semaphore) + { + + /* Semaphore is already created, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } +#endif + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual semaphore create function. */ + status = _tx_semaphore_create(semaphore_ptr, name_ptr, initial_count); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_delete.c b/3rd_party/threadx/common/src/txe_semaphore_delete.c new file mode 100644 index 00000000..5727119f --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_delete.c @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore delete function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* */ +/* OUTPUT */ +/* */ +/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_delete Actual delete semaphore function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for invalid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Check for invalid caller of this function. */ + + /* Is the caller an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Is the caller the system timer thread? */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } +#endif + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual semaphore delete function. */ + status = _tx_semaphore_delete(semaphore_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_get.c b/3rd_party/threadx/common/src/txe_semaphore_get.c new file mode 100644 index 00000000..f5d1209c --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_get.c @@ -0,0 +1,150 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore get function call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */ +/* TX_WAIT_ERROR Invalid wait option */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_get Actual get semaphore function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option) +{ + +UINT status; + +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for invalid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Check for a wait option error. Only threads are allowed any form of + suspension. */ + if (wait_option != TX_NO_WAIT) + { + + /* Is the call from an ISR or Initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + else + { + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Is the current thread the timer thread? */ + if (current_thread == &_tx_timer_thread) + { + + /* A non-thread is trying to suspend, return appropriate error code. */ + status = TX_WAIT_ERROR; + } + } +#endif + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual get semaphore function. */ + status = _tx_semaphore_get(semaphore_ptr, wait_option); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_info_get.c b/3rd_party/threadx/common/src/txe_semaphore_info_get.c new file mode 100644 index 00000000..7789ea9f --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_info_get.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* name Destination for the semaphore name*/ +/* current_value Destination for current value of */ +/* the semaphore */ +/* first_suspended Destination for pointer of first */ +/* thread suspended on semaphore */ +/* suspended_count Destination for suspended count */ +/* next_semaphore Destination for pointer to next */ +/* semaphore on the created list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_info_get Actual semaphore info get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, + TX_THREAD **first_suspended, ULONG *suspended_count, + TX_SEMAPHORE **next_semaphore) +{ + +UINT status; + + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for a valid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Otherwise, call the actual semaphore information get service. */ + status = _tx_semaphore_info_get(semaphore_ptr, name, current_value, first_suspended, + suspended_count, next_semaphore); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_prioritize.c b/3rd_party/threadx/common/src/txe_semaphore_prioritize.c new file mode 100644 index 00000000..b00c82d4 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_prioritize.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_semaphore_prioritize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore prioritize call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_prioritize Actual semaphore prioritize */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr) +{ + +UINT status; + + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for a valid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Call actual semaphore prioritize function. */ + status = _tx_semaphore_prioritize(semaphore_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_put.c b/3rd_party/threadx/common/src/txe_semaphore_put.c new file mode 100644 index 00000000..591026ed --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_put.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_put PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore put function call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore control block*/ +/* */ +/* OUTPUT */ +/* */ +/* TX_SEMAPHORE_ERROR Invalid semaphore pointer */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_put Actual put semaphore function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_put(TX_SEMAPHORE *semaphore_ptr) +{ + +UINT status; + + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for invalid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Call actual put semaphore function. */ + status = _tx_semaphore_put(semaphore_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_semaphore_put_notify.c b/3rd_party/threadx/common/src/txe_semaphore_put_notify.c new file mode 100644 index 00000000..f73e1f99 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_semaphore_put_notify.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Semaphore */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_semaphore.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_semaphore_put_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the semaphore put notify */ +/* callback function call. */ +/* */ +/* INPUT */ +/* */ +/* semaphore_ptr Pointer to semaphore */ +/* semaphore_put_notify Application callback function */ +/* (TX_NULL disables notify) */ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_semaphore_put_notify Actual semaphore put notify */ +/* call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)) +{ + +UINT status; + + + /* Check for an invalid semaphore pointer. */ + if (semaphore_ptr == TX_NULL) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + + /* Now check for invalid semaphore ID. */ + else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID) + { + + /* Semaphore pointer is invalid, return appropriate error code. */ + status = TX_SEMAPHORE_ERROR; + } + else + { + + /* Call actual semaphore put notify function. */ + status = _tx_semaphore_put_notify(semaphore_ptr, semaphore_put_notify); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_create.c b/3rd_party/threadx/common/src/txe_thread_create.c new file mode 100644 index 00000000..75f5e660 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_create.c @@ -0,0 +1,313 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread create function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* name Pointer to thread name string */ +/* entry_function Entry function of the thread */ +/* entry_input 32-bit input value to thread */ +/* stack_start Pointer to start of stack */ +/* stack_size Stack size in bytes */ +/* priority Priority of thread (0-31) */ +/* preempt_threshold Preemption threshold */ +/* time_slice Thread time-slice value */ +/* auto_start Automatic start selection */ +/* thread_control_block_size Size of thread control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_PTR_ERROR Invalid entry point or stack */ +/* address */ +/* TX_SIZE_ERROR Invalid stack size -too small */ +/* TX_PRIORITY_ERROR Invalid thread priority */ +/* TX_THRESH_ERROR Invalid preemption threshold */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_create Actual thread create function */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, + VOID (*entry_function)(ULONG id), ULONG entry_input, + VOID *stack_start, ULONG stack_size, + UINT priority, UINT preempt_threshold, + ULONG time_slice, UINT auto_start, UINT thread_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +UINT break_flag; +ULONG i; +TX_THREAD *next_thread; +VOID *stack_end; +UCHAR *work_ptr; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread control block size. */ + else if (thread_control_block_size != (sizeof(TX_THREAD))) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + break_flag = TX_FALSE; + next_thread = _tx_thread_created_ptr; + work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(stack_start); + work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (stack_size - ((ULONG) 1))); + stack_end = TX_UCHAR_TO_VOID_POINTER_CONVERT(work_ptr); + for (i = ((ULONG) 0); i < _tx_thread_created_count; i++) + { + + /* Determine if this thread matches the thread in the list. */ + if (thread_ptr == next_thread) + { + + /* Set the break flag. */ + break_flag = TX_TRUE; + } + + /* Determine if we need to break the loop. */ + if (break_flag == TX_TRUE) + { + + /* Yes, break out of the loop. */ + break; + } + + /* Check the stack pointer to see if it overlaps with this thread's stack. */ + if (stack_start >= next_thread -> tx_thread_stack_start) + { + + if (stack_start < next_thread -> tx_thread_stack_end) + { + + /* This stack overlaps with an existing thread, clear the stack pointer to + force a stack error below. */ + stack_start = TX_NULL; + + /* Set the break flag. */ + break_flag = TX_TRUE; + } + } + + /* Check the end of the stack to see if it is inside this thread's stack area as well. */ + if (stack_end >= next_thread -> tx_thread_stack_start) + { + + if (stack_end < next_thread -> tx_thread_stack_end) + { + + /* This stack overlaps with an existing thread, clear the stack pointer to + force a stack error below. */ + stack_start = TX_NULL; + + /* Set the break flag. */ + break_flag = TX_TRUE; + } + } + + /* Move to the next thread. */ + next_thread = next_thread -> tx_thread_created_next; + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate thread. */ + if (thread_ptr == next_thread) + { + + /* Thread is already created, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for invalid starting address of stack. */ + else if (stack_start == TX_NULL) + { + + /* Invalid stack or entry point, return appropriate error code. */ + status = TX_PTR_ERROR; + } + + /* Check for invalid thread entry point. */ + else if (entry_function == TX_NULL) + { + + /* Invalid stack or entry point, return appropriate error code. */ + status = TX_PTR_ERROR; + } + + /* Check the stack size. */ + else if (stack_size < ((ULONG) TX_MINIMUM_STACK)) + { + + /* Stack is not big enough, return appropriate error code. */ + status = TX_SIZE_ERROR; + } + + /* Check the priority specified. */ + else if (priority >= ((UINT) TX_MAX_PRIORITIES)) + { + + /* Invalid priority selected, return appropriate error code. */ + status = TX_PRIORITY_ERROR; + } + + /* Check preemption threshold. */ + else if (preempt_threshold > priority) + { + + /* Invalid preempt threshold, return appropriate error code. */ + status = TX_THRESH_ERROR; + } + + /* Check the start selection. */ + else if (auto_start > TX_AUTO_START) + { + + /* Invalid auto start selection, return appropriate error code. */ + status = TX_START_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (current_thread == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual thread create function. */ + status = _tx_thread_create(thread_ptr, name_ptr, entry_function, entry_input, + stack_start, stack_size, priority, preempt_threshold, + time_slice, auto_start); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_delete.c b/3rd_party/threadx/common/src/txe_thread_delete.c new file mode 100644 index 00000000..55b98abe --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_delete.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread delete function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_delete Actual thread delete function */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_delete(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Check for invalid caller of this function. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Check for an invalid thread pointer. */ + else if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Call actual thread delete function. */ + status = _tx_thread_delete(thread_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_entry_exit_notify.c b/3rd_party/threadx/common/src/txe_thread_entry_exit_notify.c new file mode 100644 index 00000000..0dec7dba --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_entry_exit_notify.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_entry_exit_notify PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread entry/exit notify */ +/* callback function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread */ +/* thread_entry_exit_notify Pointer to notify callback */ +/* function, TX_NULL to disable*/ +/* */ +/* OUTPUT */ +/* */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_entry_exit_notify Actual entry/exit notify */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type)) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Call actual thread entry/exit notify function. */ + status = _tx_thread_entry_exit_notify(thread_ptr, thread_entry_exit_notify); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_info_get.c b/3rd_party/threadx/common/src/txe_thread_info_get.c new file mode 100644 index 00000000..6d0e594f --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_info_get.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control block */ +/* name Destination for the thread name */ +/* state Destination for thread state */ +/* run_count Destination for thread run count */ +/* priority Destination for thread priority */ +/* preemption_threshold Destination for thread preemption-*/ +/* threshold */ +/* time_slice Destination for thread time-slice */ +/* next_thread Destination for next created */ +/* thread */ +/* next_suspended_thread Destination for next suspended */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_info_get Actual thread information get */ +/* service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, + UINT *priority, UINT *preemption_threshold, ULONG *time_slice, + TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Call the actual thread information get service. */ + status = _tx_thread_info_get(thread_ptr, name, state, run_count, priority, preemption_threshold, + time_slice, next_thread, next_suspended_thread); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_preemption_change.c b/3rd_party/threadx/common/src/txe_thread_preemption_change.c new file mode 100644 index 00000000..8cfee279 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_preemption_change.c @@ -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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_preemption_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the preemption threshold change */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread */ +/* new_threshold New preemption threshold */ +/* old_threshold Old preemption threshold */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_PTR_ERROR Invalid old threshold pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_preemption_change Actual preempt change function*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, UINT *old_threshold) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for a valid old threshold pointer. */ + else if (old_threshold == TX_NULL) + { + + /* Invalid destination pointer, return appropriate error code. */ + status = TX_PTR_ERROR; + } + + /* Check for invalid caller of this function. */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Determine if the preemption-threshold is valid. */ + else if (new_threshold > thread_ptr -> tx_thread_user_priority) + { + + /* Return an error status. */ + status = TX_THRESH_ERROR; + } + else + { + + /* Call actual change thread preemption function. */ + status = _tx_thread_preemption_change(thread_ptr, new_threshold, old_threshold); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_priority_change.c b/3rd_party/threadx/common/src/txe_thread_priority_change.c new file mode 100644 index 00000000..fcccbc43 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_priority_change.c @@ -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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_priority_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the change priority function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* new_priority New thread priority */ +/* old_priority Old thread priority */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_PTR_ERROR Invalid old priority pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_priority_change Actual priority change */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_priority_change(TX_THREAD *thread_ptr, UINT new_priority, UINT *old_priority) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for a valid old priority pointer. */ + else if (old_priority == TX_NULL) + { + + /* Invalid destination pointer, return appropriate error code. */ + status = TX_PTR_ERROR; + } + + /* Determine if the priority is legal. */ + else if (new_priority >= ((UINT) TX_MAX_PRIORITIES)) + { + + /* Return an error status. */ + status = TX_PRIORITY_ERROR; + } + + /* Check for invalid caller of this function. */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + + /* Call actual change thread priority function. */ + status = _tx_thread_priority_change(thread_ptr, new_priority, old_priority); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_relinquish.c b/3rd_party/threadx/common/src/txe_thread_relinquish.c new file mode 100644 index 00000000..f0a6ea83 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_relinquish.c @@ -0,0 +1,94 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_relinquish PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks to make sure a thread is executing before the */ +/* relinquish is executed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_relinquish Actual thread relinquish call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _txe_thread_relinquish(VOID) +{ + +TX_THREAD *current_thread; + + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Make sure a thread is executing. */ + if (current_thread != TX_NULL) + { + + /* Now make sure the call is not from an ISR or Initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0)) + { + + /* Okay to call the real relinquish function. */ + _tx_thread_relinquish(); + } + } +} + diff --git a/3rd_party/threadx/common/src/txe_thread_reset.c b/3rd_party/threadx/common/src/txe_thread_reset.c new file mode 100644 index 00000000..18f962ac --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_reset.c @@ -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 */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_reset PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread reset function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to reset */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Service return status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_reset Actual thread reset function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_reset(TX_THREAD *thread_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *current_thread; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for an invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(current_thread) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (current_thread == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt or initialization call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual thread reset function. */ + status = _tx_thread_reset(thread_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_resume.c b/3rd_party/threadx/common/src/txe_thread_resume.c new file mode 100644 index 00000000..33a9abe9 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_resume.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_resume PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the resume thread function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to resume */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_resume Actual thread resume function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_resume(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Call actual thread resume function. */ + status = _tx_thread_resume(thread_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_suspend.c b/3rd_party/threadx/common/src/txe_thread_suspend.c new file mode 100644 index 00000000..f368d4ea --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_suspend.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_suspend PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread suspend function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_suspend Actual thread suspension */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_suspend(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Call actual thread suspend function. */ + status = _tx_thread_suspend(thread_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_terminate.c b/3rd_party/threadx/common/src/txe_thread_terminate.c new file mode 100644 index 00000000..0865c677 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_terminate.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_terminate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread terminate function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_terminate Actual thread terminate */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_terminate(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for invalid caller of this function. */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + + /* Call actual thread terminate function. */ + status = _tx_thread_terminate(thread_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_time_slice_change.c b/3rd_party/threadx/common/src/txe_thread_time_slice_change.c new file mode 100644 index 00000000..be68afb3 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_time_slice_change.c @@ -0,0 +1,124 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_time_slice_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the time slice change function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread */ +/* new_time_slice New time slice */ +/* old_time_slice Old time slice */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_time_slice_change Actual time-slice change */ +/* function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for a valid old time-slice pointer. */ + else if (old_time_slice == TX_NULL) + { + + /* Invalid destination pointer, return appropriate error code. */ + status = TX_PTR_ERROR; + } + + /* Check for invalid caller of this function. */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + + /* Call actual change time slice function. */ + status = _tx_thread_time_slice_change(thread_ptr, new_time_slice, old_time_slice); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_thread_wait_abort.c b/3rd_party/threadx/common/src/txe_thread_wait_abort.c new file mode 100644 index 00000000..9482e809 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_thread_wait_abort.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_wait_abort PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the thread wait abort function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread to abort the wait on */ +/* */ +/* OUTPUT */ +/* */ +/* status Return completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_wait_abort Actual wait abort function */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_thread_wait_abort(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + else + { + + /* Call actual thread wait abort function. */ + status = _tx_thread_wait_abort(thread_ptr); + } + + /* Return status to the caller. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_timer_activate.c b/3rd_party/threadx/common/src/txe_timer_activate.c new file mode 100644 index 00000000..9a50e39e --- /dev/null +++ b/3rd_party/threadx/common/src/txe_timer_activate.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_timer_activate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the activate application timer */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TIMER_ERROR Invalid application timer */ +/* TX_ACTIVATE_ERROR Application timer already active */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_activate Actual application timer activate */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_timer_activate(TX_TIMER *timer_ptr) +{ + +UINT status; + + + /* Check for an invalid timer pointer. */ + if (timer_ptr == TX_NULL) + { + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Now check for invalid timer ID. */ + else if (timer_ptr -> tx_timer_id != TX_TIMER_ID) + { + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + else + { + + /* Call actual application timer activate function. */ + status = _tx_timer_activate(timer_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_timer_change.c b/3rd_party/threadx/common/src/txe_timer_change.c new file mode 100644 index 00000000..d6db7755 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_timer_change.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_timer_change PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the application timer change */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* initial_ticks Initial expiration ticks */ +/* reschedule_ticks Reschedule ticks */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TIMER_ERROR Invalid application timer pointer */ +/* TX_TICK_ERROR Invalid initial tick value of 0 */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_change Actual timer change function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks) +{ + +UINT status; + + + /* Check for an invalid timer pointer. */ + if (timer_ptr == TX_NULL) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Now check for invalid timer ID. */ + else if (timer_ptr -> tx_timer_id != TX_TIMER_ID) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Check for an illegal initial tick value. */ + else if (initial_ticks == ((ULONG) 0)) + { + + /* Invalid initial tick value, return appropriate error code. */ + status = TX_TICK_ERROR; + } + + /* Check for invalid caller of this function. */ + else if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + + /* Call actual application timer function. */ + status = _tx_timer_change(timer_ptr, initial_ticks, reschedule_ticks); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_timer_create.c b/3rd_party/threadx/common/src/txe_timer_create.c new file mode 100644 index 00000000..de08c053 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_timer_create.c @@ -0,0 +1,239 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_timer_create PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the create application timer */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* name_ptr Pointer to timer name */ +/* expiration_function Application expiration function */ +/* initial_ticks Initial expiration ticks */ +/* reschedule_ticks Reschedule ticks */ +/* auto_activate Automatic activation flag */ +/* timer_control_block_size Size of timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TIMER_ERROR Invalid timer control block */ +/* TX_TICK_ERROR Invalid initial expiration count */ +/* TX_ACTIVATE_ERROR Invalid timer activation option */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_system_preempt_check Check for preemption */ +/* _tx_timer_create Actual timer create function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, + VOID (*expiration_function)(ULONG id), ULONG expiration_input, + ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT status; +ULONG i; +TX_TIMER *next_timer; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for a NULL timer pointer. */ + if (timer_ptr == TX_NULL) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Now check for invalid control block size. */ + else if (timer_control_block_size != (sizeof(TX_TIMER))) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + else + { + + /* Disable interrupts. */ + TX_DISABLE + + /* Increment the preempt disable flag. */ + _tx_thread_preempt_disable++; + + /* Restore interrupts. */ + TX_RESTORE + + /* Next see if it is already in the created list. */ + next_timer = _tx_timer_created_ptr; + for (i = ((ULONG) 0); i < _tx_timer_created_count; i++) + { + + /* Determine if this timer matches the current timer in the list. */ + if (timer_ptr == next_timer) + { + + break; + } + else + { + + /* Move to next timer. */ + next_timer = next_timer -> tx_timer_created_next; + } + } + + /* Disable interrupts. */ + TX_DISABLE + + /* Decrement the preempt disable flag. */ + _tx_thread_preempt_disable--; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for preemption. */ + _tx_thread_system_preempt_check(); + + /* At this point, check to see if there is a duplicate timer. */ + if (timer_ptr == next_timer) + { + + /* Timer is already created, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Check for an illegal initial tick value. */ + else if (initial_ticks == ((ULONG) 0)) + { + + /* Invalid initial tick value, return appropriate error code. */ + status = TX_TICK_ERROR; + } + else + { + + /* Check for an illegal activation. */ + if (auto_activate != TX_AUTO_ACTIVATE) + { + + /* And activation is not the other value. */ + if (auto_activate != TX_NO_ACTIVATE) + { + + /* Invalid activation selected, return appropriate error code. */ + status = TX_ACTIVATE_ERROR; + } + } + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Check for invalid caller of this function. First check for a calling thread. */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } +#endif + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + } + + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual application timer create function. */ + status = _tx_timer_create(timer_ptr, name_ptr, expiration_function, expiration_input, + initial_ticks, reschedule_ticks, auto_activate); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_timer_deactivate.c b/3rd_party/threadx/common/src/txe_timer_deactivate.c new file mode 100644 index 00000000..d5379001 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_timer_deactivate.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_timer_deactivate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the deactivate application timer */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TIMER_ERROR Invalid application timer pointer */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_deactivate Actual timer deactivation function*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_timer_deactivate(TX_TIMER *timer_ptr) +{ + +UINT status; + + + /* Check for an invalid timer pointer. */ + if (timer_ptr == TX_NULL) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Now check for invalid timer ID. */ + else if (timer_ptr -> tx_timer_id != TX_TIMER_ID) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + else + { + + /* Call actual application timer deactivate function. */ + status = _tx_timer_deactivate(timer_ptr); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_timer_delete.c b/3rd_party/threadx/common/src/txe_timer_delete.c new file mode 100644 index 00000000..0502efd2 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_timer_delete.c @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_timer_delete PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the delete application timer */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TIMER_ERROR Invalid application timer pointer */ +/* TX_CALLER_ERROR Invalid caller of this function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_delete Actual timer delete function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_timer_delete(TX_TIMER *timer_ptr) +{ + +UINT status; +#ifndef TX_TIMER_PROCESS_IN_ISR +TX_THREAD *thread_ptr; +#endif + + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Default status to success. */ + status = TX_SUCCESS; +#endif + + /* Check for an invalid timer pointer. */ + if (timer_ptr == TX_NULL) + { + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Now check for invalid timer ID. */ + else if (timer_ptr -> tx_timer_id != TX_TIMER_ID) + { + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Check for invalid caller of this function. */ + + /* Is the caller an ISR or Initialization? */ + else if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + else + { + +#ifndef TX_TIMER_PROCESS_IN_ISR + + /* Pickup thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr) + + /* Is the caller the system timer thread? */ + if (thread_ptr == &_tx_timer_thread) + { + + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { +#endif + + /* Call actual application timer delete function. */ + status = _tx_timer_delete(timer_ptr); + +#ifndef TX_TIMER_PROCESS_IN_ISR + } +#endif + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/common/src/txe_timer_info_get.c b/3rd_party/threadx/common/src/txe_timer_info_get.c new file mode 100644 index 00000000..b2865983 --- /dev/null +++ b/3rd_party/threadx/common/src/txe_timer_info_get.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_timer_info_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the timer information get */ +/* service. */ +/* */ +/* INPUT */ +/* */ +/* timer_ptr Pointer to timer control block */ +/* name Destination for the timer name */ +/* active Destination for active flag */ +/* remaining_ticks Destination for remaining ticks */ +/* before expiration */ +/* reschedule_ticks Destination for reschedule ticks */ +/* next_timer Destination for next timer on the */ +/* created list */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TIMER_ERROR Invalid timer pointer */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_info_get Actual info get call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, + ULONG *reschedule_ticks, TX_TIMER **next_timer) +{ + +UINT status; + + + /* Check for an invalid timer pointer. */ + if (timer_ptr == TX_NULL) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + + /* Now check for invalid timer ID. */ + else if (timer_ptr -> tx_timer_id != TX_TIMER_ID) + { + + /* Timer pointer is invalid, return appropriate error code. */ + status = TX_TIMER_ERROR; + } + else + { + + /* Otherwise, call the actual timer information get service. */ + status = _tx_timer_info_get(timer_ptr, name, active, remaining_ticks, reschedule_ticks, next_timer); + } + + /* Return completion status. */ + return(status); +} + diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/inc/tx_port.h b/3rd_party/threadx/ports/cortex_m4/ac5/inc/tx_port.h new file mode 100644 index 00000000..2dd0b792 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/inc/tx_port.h @@ -0,0 +1,474 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/AC5 */ +/* 6.1.6 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, 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. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */ +/* macro definition, */ +/* resulting in version 6.1.6 */ +/* */ +/**************************************************************************/ + +#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 +#include + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 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-M3 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 + + +/* 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 +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) + + +#ifndef TX_MISRA_ENABLE + +register unsigned int _ipsr __asm("ipsr"); + +#endif + + +#ifdef __TARGET_FPU_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 + +#ifdef TX_SOURCE_CODE + +register ULONG _control __asm("control"); + +#endif +#endif + +/* 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 = _control; \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _control = _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 + +void _tx_vfp_access(void); + +#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 = _control; \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _control = _tx_vfp_state; \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _control; \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + _tx_vfp_access(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _control; \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _control = _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 + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif + + +/* 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 +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr) +#else +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif +#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++; + + +/* Determine if the ARM architecture has the CLZ instruction. This is available on + architectures v5 and above. If available, redefine the macro for calculating the + lowest bit set. */ + +#ifndef TX_DISABLE_INLINE + +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m))); + +#endif + + +/* Define ThreadX interrupt lockout and restore macros for protection on + access of critical kernel information. The restore interrupt macro must + restore the interrupt posture of the running thread prior to the value + present prior to the disable macro. In most cases, the save area macro + is used to define a local function save area for the disable and restore + macros. */ + +#ifdef TX_DISABLE_INLINE + +UINT _tx_thread_interrupt_disable(VOID); +VOID _tx_thread_interrupt_restore(UINT previous_posture); + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); + +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); + +#else + +#define TX_INTERRUPT_SAVE_AREA UINT was_masked; +#define TX_DISABLE was_masked = __disable_irq(); +#define TX_RESTORE if (was_masked == 0) __enable_irq(); + +#define _tx_thread_system_return _tx_thread_system_return_inline + + +static void _tx_thread_system_return_inline(void) +{ +unsigned int was_masked; + + + /* Set PendSV to invoke ThreadX scheduler. */ + *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + if (_ipsr == 0) + { + was_masked = __disable_irq(); + __enable_irq(); + if (was_masked != 0) + __disable_irq(); + } +} +#endif + + +/* Define FPU extension for the Cortex-M4. 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-M4/AC5 Version 6.1.6 *"; +#else +#ifdef TX_MISRA_ENABLE +extern CHAR _tx_version_id[100]; +#else +extern CHAR _tx_version_id[]; +#endif +#endif + + +#endif + + + + diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/readme_threadx.txt b/3rd_party/threadx/ports/cortex_m4/ac5/readme_threadx.txt new file mode 100644 index 00000000..353c0ea7 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/readme_threadx.txt @@ -0,0 +1,216 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M4 + + Using ARM Compiler 5 (AC5) + + +1. Building the ThreadX run-time Library + +First make sure you are in the "example_build" directory. Also, make sure that +you have setup your path and other environment variables necessary for the AC5 +development environment. 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 +Windows-based 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 simulator. + + +3. System Initialization + +The entry point in ThreadX for the Cortex-M4 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-M4 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.Uv2 +project to debugging 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-M4 +targets. There are a certain set of requirements that are defined in the +following sub-sections: + + +6.1 Vector Area + +The Cortex-M4 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-M4 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: + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + tx_thread_schedule.s Fix compilation error + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_thread_schedule.s Added low power feature + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using AC5 tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_initialize_low_level.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_initialize_low_level.s new file mode 100644 index 00000000..56a46f71 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_initialize_low_level.s @@ -0,0 +1,255 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Initialize */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IMPORT _tx_thread_system_stack_ptr + IMPORT _tx_initialize_unused_memory + IMPORT _tx_thread_context_save + IMPORT _tx_thread_context_restore + IMPORT _tx_timer_interrupt + IMPORT __main + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$ZI$$Base| + IMPORT |Image$$ZI$$Limit| + IMPORT __tx_PendSVHandler +; +; +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 __tx_PendSVHandler ; PendSV + DCD __tx_SysTickHandler ; SysTick + 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 + IF {TARGET_FPU_VFP} = {TRUE} + 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-M4/AC5 */ +;/* 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) +;{ + EXPORT _tx_initialize_low_level +_tx_initialize_low_level +; +; /* Disable interrupts during ThreadX initialization. */ +; + CPSID i +; +; /* Set base of available memory to end of non-initialised RAM area. */ +; + LDR r0, =_tx_initialize_unused_memory ; Build address of unused memory pointer + LDR r1, =|Image$$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, =__tx_vectors ; Pickup address of vector table + STR r1, [r0, #0xD08] ; Set vector table address +; +; /* Enable the cycle count register. */ +; +; LDR r0, =0xE0001000 ; Build address of DWT register +; LDR r1, [r0] ; Pickup the current value +; ORR r1, r1, #1 ; Set the CYCCNTENA bit +; STR r1, [r0] ; Enable the cycle count register +; +; /* Set system stack pointer from vector value. */ +; + LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer + LDR r1, =__tx_vectors ; Pickup address of vector table + LDR r1, [r1] ; Pickup reset stack pointer + STR r1, [r0] ; Save system stack pointer +; +; /* Configure SysTick. */ +; + MOV r0, #0xE000E000 ; Build address of NVIC registers + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] ; Setup SysTick Reload Value + MOV r1, #0x7 ; Build SysTick Control Enable Value + STR r1, [r0, #0x10] ; Setup SysTick Control +; +; /* Configure handler priorities. */ +; + LDR r1, =0x00000000 ; Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] ; Setup System Handlers 4-7 Priority Registers + + LDR r1, =0xFF000000 ; SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] ; Setup System Handlers 8-11 Priority Registers + ; Note: SVC must be lowest priority, which is 0xFF + + LDR r1, =0x40FF0000 ; SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] ; Setup System Handlers 12-15 Priority Registers + ; Note: PnSV must be lowest priority, which is 0xFF +; +; /* Return to caller. */ +; + BX lr +;} +; +; +;/* Define 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} + +; /* Do interrupt handler work here */ +; /* .... */ + + POP {r0, lr} + BX LR +; } + + EXPORT __tx_SysTickHandler +__tx_SysTickHandler +; VOID TimerInterruptHandler (VOID) +; { +; + PUSH {r0, lr} + BL _tx_timer_interrupt + POP {r0, lr} + BX LR +; } + + EXPORT __tx_NMIHandler +__tx_NMIHandler + B __tx_NMIHandler + + EXPORT __tx_DBGHandler +__tx_DBGHandler + B __tx_DBGHandler + + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_context_restore.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_context_restore.s new file mode 100644 index 00000000..0ed36142 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_context_restore.s @@ -0,0 +1,91 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IMPORT _tx_execution_isr_exit + ENDIF +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_context_restore Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, 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. */ +;/* This function restores the interrupt context if it is processing a */ +;/* nested interrupt. If not, it returns to the interrupt thread if no */ +;/* preemption is necessary. Otherwise, if preemption is necessary or */ +;/* if no thread was running, the function returns to the scheduler. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_thread_schedule Thread scheduling routine */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ISRs Interrupt Service Routines */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_context_restore(VOID) +;{ + EXPORT _tx_thread_context_restore +_tx_thread_context_restore + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY +; +; /* Call the ISR exit function to indicate an ISR is complete. */ +; + PUSH {r0,lr} ; Save ISR lr + BL _tx_execution_isr_exit ; Call the ISR exit function + POP {r0,lr} ; Restore ISR lr + ENDIF +; + POP {lr} + BX lr +;} + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_context_save.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_context_save.s new file mode 100644 index 00000000..03ec67e6 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_context_save.s @@ -0,0 +1,91 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IMPORT _tx_execution_isr_enter + ENDIF +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_context_save Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, 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. */ +;/* This function saves the context of an executing thread in the */ +;/* beginning of interrupt processing. The function also ensures that */ +;/* the system stack is used upon return to the calling ISR. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ISRs */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_context_save(VOID) +;{ + EXPORT _tx_thread_context_save +_tx_thread_context_save + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY +; +; /* Call the ISR enter function to indicate an ISR is executing. */ +; + PUSH {r0, lr} ; Save ISR lr + BL _tx_execution_isr_enter ; Call the ISR enter function + POP {r0, lr} ; Recover ISR lr + ENDIF +; +; /* Return to interrupt processing. */ +; + BX lr ; Return to interrupt processing caller +;} + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_control.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_control.s new file mode 100644 index 00000000..ef983f17 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_control.s @@ -0,0 +1,76 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for changing the interrupt lockout */ +;/* posture of the system. */ +;/* */ +;/* INPUT */ +;/* */ +;/* new_posture New interrupt lockout posture */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* old_posture Old interrupt lockout posture */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;UINT _tx_thread_interrupt_control(UINT new_posture) +;{ + EXPORT _tx_thread_interrupt_control +_tx_thread_interrupt_control +; +; /* Pickup current interrupt lockout posture. */ +; + MRS r1, PRIMASK + MSR PRIMASK, r0 + MOV r0, r1 + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_disable.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_disable.s new file mode 100644 index 00000000..b0b31cb0 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_disable.s @@ -0,0 +1,75 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_interrupt_disable Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation. */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for disabling interrupts and returning */ +;/* the previous interrupt lockout posture. */ +;/* */ +;/* INPUT */ +;/* */ +;/* old_posture Old interrupt lockout posture */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;UINT _tx_thread_interrupt_disable(UINT new_posture) +;{ + EXPORT _tx_thread_interrupt_disable +_tx_thread_interrupt_disable +; +; /* Return current interrupt lockout posture. */ +; + MRS r0, PRIMASK + CPSID i + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_restore.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_restore.s new file mode 100644 index 00000000..c7350e36 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_interrupt_restore.s @@ -0,0 +1,74 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_interrupt_restore Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation. */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for restoring the previous */ +;/* interrupt lockout posture. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* previous_posture Previous interrupt posture */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_interrupt_restore(UINT new_posture) +;{ + EXPORT _tx_thread_interrupt_restore +_tx_thread_interrupt_restore +; +; /* Restore previous interrupt lockout posture. */ +; + MSR PRIMASK, r0 + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_schedule.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_schedule.s new file mode 100644 index 00000000..0b3888a6 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_schedule.s @@ -0,0 +1,309 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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 :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IMPORT _tx_execution_thread_enter + IMPORT _tx_execution_thread_exit + ENDIF + IF :DEF:TX_LOW_POWER + IMPORT tx_low_power_enter + IMPORT tx_low_power_exit + ENDIF +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_schedule Cortex-M4/AC5 */ +;/* 6.1.5 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function waits for a thread control block pointer to appear in */ +;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +;/* in the variable, the corresponding thread is resumed. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* _tx_initialize_kernel_enter ThreadX entry function */ +;/* _tx_thread_system_return Return to system from thread */ +;/* _tx_thread_context_restore Restore thread's context */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* 03-02-2021 Scott Larson Modified comment(s), add */ +;/* low power code, */ +;/* resulting in version 6.1.5 */ +;/* */ +;/**************************************************************************/ +;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 routines 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. */ +; + IF {TARGET_FPU_VFP} = {TRUE} + MRS r0, CONTROL ; Pickup current CONTROL register + BIC r0, r0, #4 ; Clear the FPCA bit + MSR CONTROL, r0 ; Setup new CONTROL register + ENDIF +; +; /* Enable the 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 :DEF: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 + MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address + MOV32 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 + IF {TARGET_FPU_VFP} = {TRUE} + 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 + MOV32 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! */ +; + 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 + MOV32 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 :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY +; +; /* Call the thread entry function to indicate the thread is executing. */ +; + PUSH {r0, r1} ; Save r0/r1 + BL _tx_execution_thread_enter ; Call the thread execution enter function + POP {r0, r1} ; Recover r3 + ENDIF +; +; /* Restore the thread context and PSP. */ +; + LDR r12, [r1, #8] ; Pickup thread's stack pointer + LDMIA r12!, {LR} ; Pickup LR + IF {TARGET_FPU_VFP} = {TRUE} + 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! + + IF :DEF:TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_enter ; Possibly enter low power mode + POP {r0-r3} + ENDIF + + IF :DEF:TX_ENABLE_WFI + DSB ; Ensure no outstanding memory transactions + WFI ; Wait for interrupt + ISB ; Ensure pipeline is flushed + ENDIF + + IF :DEF: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 + + IF {TARGET_FPU_VFP} = {TRUE} + EXPORT 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 + + EXPORT tx_thread_fpu_disable +tx_thread_fpu_disable +; +; /* Automatic VPF logic is supported, this function is present only for +; backward compatibility purposes and therefore simply returns. */ +; + BX LR ; Return to caller + + EXPORT _tx_vfp_access +_tx_vfp_access + VMOV.F32 s0, s0 ; Simply access the VFP + BX lr ; Return to caller + + + ENDIF + + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_stack_build.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_stack_build.s new file mode 100644 index 00000000..f548938b --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_stack_build.s @@ -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 */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_stack_build Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function builds a stack frame on the supplied thread's stack. */ +;/* The stack frame results in a fake interrupt return to the supplied */ +;/* function pointer. */ +;/* */ +;/* INPUT */ +;/* */ +;/* thread_ptr Pointer to thread control blk */ +;/* function_ptr Pointer to return function */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* _tx_thread_create Create thread service */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;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-M4 should look like the following after it is built: +; +; Stack Top: +; LR Interrupted LR (LR at time of PENDSV) +; r4 Initial value for r4 +; r5 Initial value for r5 +; r6 Initial value for r6 +; r7 Initial value for r7 +; r8 Initial value for r8 +; r9 Initial value for r9 +; r10 Initial value for r10 +; r11 Initial value for r11 +; r0 Initial value for r0 (Hardware stack starts here!!) +; r1 Initial value for r1 +; r2 Initial value for r2 +; r3 Initial value for r3 +; r12 Initial value for r12 +; lr Initial value for lr +; pc Initial value for pc +; xPSR Initial value for xPSR +; +; Stack Bottom: (higher memory address) */ +; + LDR r2, [r0, #16] ; Pickup end of stack area + BIC r2, r2, #0x7 ; Align frame for 8-byte alignment + SUB r2, r2, #68 ; Subtract frame size + LDR r3, =0xFFFFFFFD ; Build initial LR value + STR r3, [r2, #0] ; Save on the stack +; +; /* Actually build the stack frame. */ +; + MOV r3, #0 ; Build initial register value + STR r3, [r2, #4] ; Store initial r4 + STR r3, [r2, #8] ; Store initial r5 + STR r3, [r2, #12] ; Store initial r6 + STR r3, [r2, #16] ; Store initial r7 + STR r3, [r2, #20] ; Store initial r8 + STR r3, [r2, #24] ; Store initial r9 + STR r3, [r2, #28] ; Store initial r10 + STR r3, [r2, #32] ; Store initial r11 +; +; /* Hardware stack follows. */ +; + STR r3, [r2, #36] ; Store initial r0 + STR r3, [r2, #40] ; Store initial r1 + STR r3, [r2, #44] ; Store initial r2 + STR r3, [r2, #48] ; Store initial r3 + STR r3, [r2, #52] ; Store initial r12 + MOV r3, #0xFFFFFFFF ; Poison EXC_RETURN value + STR r3, [r2, #56] ; Store initial lr + STR r1, [r2, #60] ; Store initial pc + MOV r3, #0x01000000 ; Only T-bit need be set + STR r3, [r2, #64] ; Store initial xPSR +; +; /* Setup stack pointer. */ +; thread_ptr -> tx_thread_stack_ptr = r2; +; + STR r2, [r0, #8] ; Save stack pointer in thread's + ; control block + BX lr ; Return to caller +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_system_return.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_system_return.s new file mode 100644 index 00000000..9c453e61 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_thread_system_return.s @@ -0,0 +1,85 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_system_return Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is target processor specific. It is used to transfer */ +;/* control from a thread back to the ThreadX system. Only a */ +;/* minimal context is saved since the compiler assumes temp registers */ +;/* are going to get slicked by a function call anyway. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_thread_schedule Thread scheduling loop */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ThreadX components */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;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 + 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 +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_timer_interrupt.s b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_timer_interrupt.s new file mode 100644 index 00000000..f5160174 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac5/src/tx_timer_interrupt.s @@ -0,0 +1,259 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Timer */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IMPORT _tx_timer_time_slice + IMPORT _tx_timer_system_clock + IMPORT _tx_timer_current_ptr + IMPORT _tx_timer_list_start + IMPORT _tx_timer_list_end + IMPORT _tx_timer_expired_time_slice + IMPORT _tx_timer_expired + IMPORT _tx_thread_time_slice + IMPORT _tx_timer_expiration_process + IMPORT _tx_thread_preempt_disable + IMPORT _tx_thread_current_ptr + IMPORT _tx_thread_execute_ptr +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_timer_interrupt Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function processes the hardware timer interrupt. This */ +;/* processing includes incrementing the system clock and checking for */ +;/* time slice and/or timer expiration. If either is found, the */ +;/* interrupt context save/restore functions are called along with the */ +;/* expiration functions. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_timer_expiration_process Timer expiration processing */ +;/* _tx_thread_time_slice Time slice interrupted thread */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* interrupt vector */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_timer_interrupt(VOID) +;{ + EXPORT _tx_timer_interrupt +_tx_timer_interrupt +; +; /* Upon entry to this routine, it is assumed that context save has already +; been called, and therefore the compiler scratch registers are available +; for use. */ +; +; /* Increment the system clock. */ +; _tx_timer_system_clock++; +; + MOV32 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) +; { +; + MOV32 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? +; +; /* Set the time-slice expired flag. */ +; _tx_timer_expired_time_slice = TX_TRUE; +; + MOV32 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) +; { +; + MOV32 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; +; + MOV32 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) +; + MOV32 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; +; + MOV32 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)) +; { +; + MOV32 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 + MOV32 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) +; { +; + MOV32 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) +; { +; + MOV32 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 + MOV32 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 + MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address + LDR r1, [r0] ; Pickup the current thread pointer + MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address + LDR r3, [r2] ; Pickup the execute thread pointer + MOV32 r0, 0xE000ED04 ; Build address of control register + MOV32 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 +; +; } +; +__tx_timer_nothing_expired + + DSB ; Complete all memory access + BX lr ; Return to caller +; +;} + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/inc/tx_port.h b/3rd_party/threadx/ports/cortex_m4/ac6/inc/tx_port.h new file mode 100644 index 00000000..dc1f2801 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/inc/tx_port.h @@ -0,0 +1,502 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/AC6 */ +/* 6.1.6 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, 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. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */ +/* macro definition, */ +/* resulting in version 6.1.6 */ +/* */ +/**************************************************************************/ + +#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 +#include + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 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-M7 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_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004) +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0 + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#define TX_INLINE_INITIALIZATION + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_2 +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) + + +#ifdef TX_ENABLE_FPU_SUPPORT + + +#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 + +__attribute__( ( always_inline ) ) static inline ULONG __get_control(void) +{ + +ULONG control_value; + + __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) ); + return(control_value); +} + + +__attribute__( ( always_inline ) ) static inline void __set_control(ULONG control_value) +{ + + __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" ); +} + + +#endif + + +/* 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(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_control(_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(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_control(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = __get_control(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + __asm__ volatile ("vmov.f32 s0, s0"); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = __get_control(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_control(_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 + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif + + + + +/* 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 + +__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()) +#else +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif +#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. */ + +#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++; + + +/* This ARM architecture has the CLZ instruction. This is available on + architectures v5 and above. If available, redefine the macro for calculating the + lowest bit set. */ + +#ifndef TX_DISABLE_INLINE + +#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 + + +#ifndef TX_DISABLE_INLINE + +/* Define AC6 specific macros, with in-line assembly for performance. */ + +__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void) +{ + +unsigned int primask_value; + + __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) ); + __asm__ volatile (" CPSID i" : : : "memory" ); + return(primask_value); +} + +__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value) +{ + + __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" ); +} + +__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void) +{ + +unsigned int primask_value; + + __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) ); + return(primask_value); +} + +__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) +{ + + __asm__ volatile (" CPSIE i": : : "memory" ); +} + + +__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void) +{ +unsigned int interrupt_save; + + *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + if (__get_ipsr_value() == 0) + { + interrupt_save = __get_primask_value(); + __enable_interrupts(); + __restore_interrupts(interrupt_save); + } +} + + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#define TX_DISABLE interrupt_save = __disable_interrupts(); +#define TX_RESTORE __restore_interrupts(interrupt_save); + + +/* Redefine _tx_thread_system_return for improved performance. */ + +#define _tx_thread_system_return _tx_thread_system_return_inline + + +#else + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); +#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); +#endif + + +/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing + thread. This is for legacy only, and not needed anylonger. */ + +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-M4/AC6 Version 6.1.6 *"; +#else +extern CHAR _tx_version_id[]; +#endif + + +#endif + + + + + diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/readme_threadx.txt b/3rd_party/threadx/ports/cortex_m4/ac6/readme_threadx.txt new file mode 100644 index 00000000..57e64379 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/readme_threadx.txt @@ -0,0 +1,227 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M4 + + Using the AC6 Tools + +1. Import the ThreadX Projects + +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. + + +2. Building the ThreadX run-time Library + +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. + + +3. Demonstration System + +The ThreadX demonstration is designed to execute under the DS debugger on the +MPS2_Cortex_M4 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-m4_tx.launch' file, click +'Debug As', and then click 'cortex-m4_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. + + +4. System Initialization + +The entry point in ThreadX for the Cortex-M4 using AC6 tools uses the standard AC6 +Cortex-M4 reset sequence. From the reset vector the C runtime will be initialized. + +The ThreadX tx_initialize_low_level.S file is responsible for setting up +various system data structures, the vector area, and a periodic timer interrupt +source. + +In addition, _tx_initialize_low_level determines the first available +address for use by the application, which is supplied as the sole input +parameter to your application definition function, tx_application_define. + + +5. Register Usage and Stack Frames + +The following defines the saved context stack frames for context switches +that occur as a result of interrupt handling or from thread-level API calls. +All suspended threads have the same stack frame in the Cortex-M4 version of +ThreadX. The top of the suspended thread's stack is pointed to by +tx_thread_stack_ptr in the associated thread control block TX_THREAD. + +Non-FPU Stack Frame: + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 r4 Software stacked GP registers + 0x08 r5 + 0x0C r6 + 0x10 r7 + 0x14 r8 + 0x18 r9 + 0x1C r10 + 0x20 r11 + 0x24 r0 Hardware stacked registers + 0x28 r1 + 0x2C r2 + 0x30 r3 + 0x34 r12 + 0x38 lr + 0x3C pc + 0x40 xPSR + +FPU Stack Frame (only interrupted thread with FPU enabled): + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 s16 Software stacked FPU registers + 0x08 s17 + 0x0C s18 + 0x10 s19 + 0x14 s20 + 0x18 s21 + 0x1C s22 + 0x20 s23 + 0x24 s24 + 0x28 s25 + 0x2C s26 + 0x30 s27 + 0x34 s28 + 0x38 s29 + 0x3C s30 + 0x40 s31 + 0x44 r4 Software stacked registers + 0x48 r5 + 0x4C r6 + 0x50 r7 + 0x54 r8 + 0x58 r9 + 0x5C r10 + 0x60 r11 + 0x64 r0 Hardware stacked registers + 0x68 r1 + 0x6C r2 + 0x70 r3 + 0x74 r12 + 0x78 lr + 0x7C pc + 0x80 xPSR + 0x84 s0 Hardware stacked FPU registers + 0x88 s1 + 0x8C s2 + 0x90 s3 + 0x94 s4 + 0x98 s5 + 0x9C s6 + 0xA0 s7 + 0xA4 s8 + 0xA8 s9 + 0xAC s10 + 0xB0 s11 + 0xB4 s12 + 0xB8 s13 + 0xBC s14 + 0xC0 s15 + 0xC4 fpscr + + +6. Improving Performance + +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. + + +7. Interrupt Handling + +ThreadX provides complete and high-performance interrupt handling for Cortex-M4 +targets. There are a certain set of requirements that are defined in the +following sub-sections: + + +7.1 Vector Area + +The Cortex-M4 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. + + +7.2 Managed Interrupts + +ISRs can be written completely in C (or assembly language) without any calls to +_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the +ThreadX API that is available to ISRs. + +ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table): + +void your_C_isr(void) +{ + + /* ISR processing goes here, including any needed function calls. */ +} + +ISRs written in assembly language will take the form: + + + .global your_assembly_isr + .thumb_func +your_assembly_isr: +; VOID your_assembly_isr(VOID) +; { + PUSH {r0, lr} +; +; /* Do interrupt handler work here */ +; /* BL */ + + POP {r0, lr} + BX lr +; } + +Note: the Cortex-M4 requires exception handlers to be thumb labels, this implies bit 0 set. +To accomplish this, the declaration of the label has to be preceded by the assembler directive +.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to +be inserted in the correct location in the interrupt vector table. This table is typically +located in either your runtime startup file or in the tx_initialize_low_level.S file. + + +8. FPU Support + +ThreadX for Cortex-M4 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. If saving the context of the FPU registers is needed, the ThreadX library should be re-built +with TX_ENABLE_FPU_SUPPORT defined. + + +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: + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_thread_schedule.s Added low power feature + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using AC6 tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_initialize_low_level.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_initialize_low_level.S new file mode 100644 index 00000000..29cedd0e --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_initialize_low_level.S @@ -0,0 +1,227 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the 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 _tx_timer_interrupt + .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_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-M4/AC6 */ +@/* 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) +@{ + .global _tx_initialize_low_level + .thumb_func +_tx_initialize_low_level: +@ +@ /* Disable interrupts during ThreadX initialization. */ +@ + CPSID i +@ +@ /* Set base of available memory to end of non-initialised RAM area. */ +@ + LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer + LDR r1, =Image$$ARM_LIB_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 +@ +@ /* 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 +@ +@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ +@ + MOV r0, #0xE000E000 @ Build address of NVIC registers + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] @ Setup SysTick Reload Value + MOV r1, #0x7 @ Build SysTick Control Enable Value + STR r1, [r0, #0x10] @ Setup SysTick Control +@ +@ /* Configure handler priorities. */ +@ + LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers + + LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers + @ Note: SVC must be lowest priority, which is 0xFF + + LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers + @ Note: PnSV must be lowest priority, which is 0xFF + +@ +@ /* Return to caller. */ +@ + BX lr +@} +@ + +@/* Define shells for each of the unused vectors. */ +@ + .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} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter @ Call the ISR enter function +#endif + +@ /* Do interrupt handler work here */ +@ /* BL .... */ + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif + POP {r0, lr} + BX LR +@ } + +@ /* System Tick timer interrupt handler */ + .global __tx_SysTickHandler + .global SysTick_Handler + .thumb_func +__tx_SysTickHandler: + .thumb_func +SysTick_Handler: +@ VOID TimerInterruptHandler (VOID) +@ { +@ + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter @ Call the ISR enter function +#endif + BL _tx_timer_interrupt +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif + POP {r0, lr} + BX LR +@ } + + +@ /* NMI, DBG handlers */ + .global __tx_NMIHandler + .thumb_func +__tx_NMIHandler: + B __tx_NMIHandler + + .global __tx_DBGHandler + .thumb_func +__tx_DBGHandler: + B __tx_DBGHandler diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_context_restore.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_context_restore.S new file mode 100644 index 00000000..daa78a7a --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_context_restore.S @@ -0,0 +1,86 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_thread_system_stack_ptr + .global _tx_thread_execute_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_thread_preempt_disable +@ +@ + .text + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_restore Cortex-M4/AC6 */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, 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. */ +@/* This function restores the interrupt context if it is processing a */ +@/* nested interrupt. If not, it returns to the interrupt thread if no */ +@/* preemption is necessary. Otherwise, if preemption is necessary or */ +@/* if no thread was running, the function returns to the scheduler. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling routine */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs Interrupt Service Routines */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_restore(VOID) +@{ + .global _tx_thread_context_restore + .thumb_func +_tx_thread_context_restore: +@ +@ /* Not needed for this port - just return! */ + BX lr +@} diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_context_save.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_context_save.S new file mode 100644 index 00000000..43f2e4c9 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_context_save.S @@ -0,0 +1,80 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr +@ +@ + .text + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_save Cortex-M4/AC6 */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, 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. */ +@/* This function saves the context of an executing thread in the */ +@/* beginning of interrupt processing. The function also ensures that */ +@/* the system stack is used upon return to the calling ISR. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_save(VOID) +@{ + .global _tx_thread_context_save + .thumb_func +_tx_thread_context_save: +@ +@ /* Not needed for this port - just return! */ + BX lr +@} diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_interrupt_control.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_interrupt_control.S new file mode 100644 index 00000000..892509bc --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_interrupt_control.S @@ -0,0 +1,81 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ + + +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ + + + .text 32 + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_interrupt_control Cortex-M4/AC6 */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is responsible for changing the interrupt lockout */ +@/* posture of the system. */ +@/* */ +@/* INPUT */ +@/* */ +@/* new_posture New interrupt lockout posture */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* old_posture Old interrupt lockout posture */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* Application Code */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +@/* */ +@/**************************************************************************/ +@/* UINT _tx_thread_interrupt_control(UINT new_posture) +{ */ + .global _tx_thread_interrupt_control + .thumb_func +_tx_thread_interrupt_control: + +@/* Pickup current interrupt lockout posture. */ + + MRS r1, PRIMASK @ Pickup current interrupt lockout + +@/* Apply the new interrupt posture. */ + + MSR PRIMASK, r0 @ Apply the new interrupt lockout + MOV r0, r1 @ Transfer old to return register + BX lr @ Return to caller + +@/* } */ diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_schedule.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_schedule.S new file mode 100644 index 00000000..bd08fc2f --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_schedule.S @@ -0,0 +1,304 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the 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_system_stack_ptr +#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-M4/AC6 */ +@/* 6.1.5 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function waits for a thread control block pointer to appear in */ +@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +@/* in the variable, the corresponding thread is resumed. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_initialize_kernel_enter ThreadX entry function */ +@/* _tx_thread_system_return Return to system from thread */ +@/* _tx_thread_context_restore Restore thread's context */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +@/* 03-02-2021 Scott Larson Modified comment(s), add */ +@/* low power code, */ +@/* resulting in version 6.1.5 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_schedule(VOID) +@{ + .global _tx_thread_schedule + .thumb_func +_tx_thread_schedule: +@ +@ /* This function should only ever be called on Cortex-M4 +@ from the first schedule request. Subsequent scheduling occurs +@ from the PendSV handling routines 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 TX_ENABLE_FPU_SUPPORT + 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 switch-out switch-in handler... Note that this handler is +@ common for both PendSV and SVCall. */ +@ + .global PendSV_Handler + .global __tx_PendSVHandler + .thumb_func +PendSV_Handler: + .thumb_func +__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 TX_ENABLE_FPU_SUPPORT + 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! */ +@ + 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/r1 + BL _tx_execution_thread_enter @ Call the thread execution enter function + POP {r0, r1} @ Recover r3 +#endif +@ +@ /* Restore the thread context and PSP. */ +@ + LDR r12, [r1, #8] @ Pickup thread's stack pointer + LDMIA r12!, {LR} @ Pickup LR +#ifdef TX_ENABLE_FPU_SUPPORT + 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 + +#ifdef TX_ENABLE_FPU_SUPPORT + + .global tx_thread_fpu_enable + .thumb_func +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 + + .global tx_thread_fpu_disable + .thumb_func +tx_thread_fpu_disable: +@ +@ /* Automatic VPF logic is supported, this function is present only for +@ backward compatibility purposes and therefore simply returns. */ +@ + BX LR @ Return to caller + +#endif diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_stack_build.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_stack_build.S new file mode 100644 index 00000000..f2639031 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_stack_build.S @@ -0,0 +1,135 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .text + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_stack_build Cortex-M4/AC6 */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function builds a stack frame on the supplied thread's stack. */ +@/* The stack frame results in a fake interrupt return to the supplied */ +@/* function pointer. */ +@/* */ +@/* INPUT */ +@/* */ +@/* thread_ptr Pointer to thread control blk */ +@/* function_ptr Pointer to return function */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_thread_create Create thread service */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.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-M4 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, #24] @ Store initial r9 + STR r3, [r2, #28] @ Store initial r10 + STR r3, [r2, #32] @ Store initial r11 +@ +@ /* Hardware stack follows. */ +@ + STR r3, [r2, #36] @ Store initial r0 + STR r3, [r2, #40] @ Store initial r1 + STR r3, [r2, #44] @ Store initial r2 + STR r3, [r2, #48] @ Store initial r3 + STR r3, [r2, #52] @ Store initial r12 + MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value + STR r3, [r2, #56] @ Store initial lr + STR r1, [r2, #60] @ Store initial pc + MOV r3, #0x01000000 @ Only T-bit need be set + STR r3, [r2, #64] @ Store initial xPSR +@ +@ /* Setup stack pointer. */ +@ thread_ptr -> tx_thread_stack_ptr = r2; +@ + STR r2, [r0, #8] @ Save stack pointer in thread's + @ control block + BX lr @ Return to caller +@} diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_system_return.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_system_return.S new file mode 100644 index 00000000..3fa421c3 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_thread_system_return.S @@ -0,0 +1,88 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ + + + .text 32 + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_system_return Cortex-M4/AC6 */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is target processor specific. It is used to transfer */ +@/* control from a thread back to the ThreadX system. Only a */ +@/* minimal context is saved since the compiler assumes temp registers */ +@/* are going to get slicked by a function call anyway. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling loop */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ThreadX components */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.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 + 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 + +@/* } */ diff --git a/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_timer_interrupt.S b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_timer_interrupt.S new file mode 100644 index 00000000..4f1175da --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/ac6/src/tx_timer_interrupt.S @@ -0,0 +1,257 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Timer */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .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-M4/AC6 */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function processes the hardware timer interrupt. This */ +@/* processing includes incrementing the system clock and checking for */ +@/* time slice and/or timer expiration. If either is found, the */ +@/* interrupt context save/restore functions are called along with the */ +@/* expiration functions. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_timer_expiration_process Timer expiration processing */ +@/* _tx_thread_time_slice Time slice interrupted thread */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* interrupt vector */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_timer_interrupt(VOID) +@{ + .global _tx_timer_interrupt + .thumb_func +_tx_timer_interrupt: +@ +@ /* Upon entry to this routine, it is assumed that context save has already +@ been called, and therefore 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 + CMP r2, #0 @ Is it non-active? + BEQ __tx_timer_no_time_slice @ 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) +@ + CMP r2, #0 @ Has it expired? + BNE __tx_timer_no_time_slice @ 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 + CMP r2, #0 @ Is there anything in the list? + BEQ __tx_timer_no_timer @ 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 + CMP r2, #0 @ Did a time-slice expire? + BNE __tx_something_expired @ 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 + CMP r0, #0 @ Did a timer expire? + BEQ __tx_timer_nothing_expired @ 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 + CMP r0, #0 @ Check for timer expiration + BEQ __tx_timer_dont_activate @ 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 + CMP r2, #0 @ See if the flag is set + BEQ __tx_timer_not_ts_expiration @ 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 +@ +@} diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/CMakeLists.txt b/3rd_party/threadx/ports/cortex_m4/gnu/CMakeLists.txt new file mode 100644 index 00000000..ba0eb088 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/CMakeLists.txt @@ -0,0 +1,18 @@ + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/inc/tx_port.h b/3rd_party/threadx/ports/cortex_m4/gnu/inc/tx_port.h new file mode 100644 index 00000000..1a335877 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/inc/tx_port.h @@ -0,0 +1,504 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/GNU */ +/* 6.1.6 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, 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. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 William E. Lamie Modified comment(s), */ +/* resulting in version 6.1 */ +/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */ +/* macro definition, */ +/* resulting in version 6.1.6 */ +/* */ +/**************************************************************************/ + +#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 +#include + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 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-M7 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_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004) +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0 + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#define TX_INLINE_INITIALIZATION + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_2 +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) + + +#ifdef TX_ENABLE_FPU_SUPPORT + + +#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 + +__attribute__( ( always_inline ) ) static inline ULONG __get_control(void) +{ + +ULONG control_value; + + __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) ); + return(control_value); +} + + +__attribute__( ( always_inline ) ) static inline void __set_control(ULONG control_value) +{ + + __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" ); +} + + +#endif + + +/* 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(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_control(_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(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_control(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = __get_control(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + __asm__ volatile ("vmov.f32 s0, s0"); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = __get_control(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_control(_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 + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif + + + + +/* 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 + +__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()) +#else +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif +#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. */ + +#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++; + + +/* This ARM architecture has the CLZ instruction. This is available on + architectures v5 and above. If available, redefine the macro for calculating the + lowest bit set. */ + +#ifndef TX_DISABLE_INLINE + +#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 + + +#ifndef TX_DISABLE_INLINE + +/* Define GNU specific macros, with in-line assembly for performance. */ + +__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void) +{ + +unsigned int primask_value; + + __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) ); + __asm__ volatile (" CPSID i" : : : "memory" ); + return(primask_value); +} + +__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value) +{ + + __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" ); +} + +__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void) +{ + +unsigned int primask_value; + + __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) ); + return(primask_value); +} + +__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) +{ + + __asm__ volatile (" CPSIE i": : : "memory" ); +} + + +__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void) +{ +unsigned int interrupt_save; + + *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + if (__get_ipsr_value() == 0) + { + interrupt_save = __get_primask_value(); + __enable_interrupts(); + __restore_interrupts(interrupt_save); + } +} + + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#define TX_DISABLE interrupt_save = __disable_interrupts(); +#define TX_RESTORE __restore_interrupts(interrupt_save); + + +/* Redefine _tx_thread_system_return for improved performance. */ + +#define _tx_thread_system_return _tx_thread_system_return_inline + + +#else + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); +#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); +#endif + + +/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing + thread. This is for legacy only, and not needed anylonger. */ + +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-M4/GNU Version 6.1.6 *"; +#else +extern CHAR _tx_version_id[]; +#endif + + +#endif + + + + + diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/readme_threadx.txt b/3rd_party/threadx/ports/cortex_m4/gnu/readme_threadx.txt new file mode 100644 index 00000000..e07ab0a3 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/readme_threadx.txt @@ -0,0 +1,229 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M4 + + Using the GNU Tools + +1. Building the ThreadX run-time Library + +First make sure you are in the "example_build" directory. Also, make sure that +you have setup your path and other environment variables necessary for the ARM +gnu (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 for Cortex-M4 + +The ThreadX demonstration is designed to execute on Cortex-M4 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-M4 using gnu tools uses the standard GNU +Cortex-M4 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-M4 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-M4 +targets. There are a certain set of requirements that are defined in the +following sub-sections: + + +6.1 Vector Area + +The Cortex-M4 vectors start at the label __tx_vectors or similar. The application may modify +the vector area according to its needs. There is code in tx_initialize_low_level() that will +configure the vector base register. + + +6.2 Managed Interrupts + +ISRs can be written completely in C (or assembly language) without any calls to +_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the +ThreadX API that is available to ISRs. + +ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table): + +void your_C_isr(void) +{ + + /* ISR processing goes here, including any needed function calls. */ +} + +ISRs written in assembly language will take the form: + + + .global your_assembly_isr + .thumb_func +your_assembly_isr: +; VOID your_assembly_isr(VOID) +; { + PUSH {r0, lr} +; +; /* Do interrupt handler work here */ +; /* BL */ + + POP {r0, lr} + BX lr +; } + +Note: the Cortex-M4 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-M4 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. If saving the context of the FPU registers is needed, the ThreadX library should be re-built +with TX_ENABLE_FPU_SUPPORT defined. + + +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: + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_thread_schedule.s Added low power feature + +09-30-2020 ThreadX update of Cortex-M4/GNU port. The following files were + changed/added for port specific version 6.1: + + *.S Modified comments and whitespace. + +05/19/2020 Initial ThreadX 6.0 version for Cortex-M4 using GNU tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_initialize_low_level.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_initialize_low_level.S new file mode 100644 index 00000000..3569f0c7 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_initialize_low_level.S @@ -0,0 +1,233 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the 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 __tx_SVCallHandler + .global __tx_PendSVHandler + .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-M4/GNU */ +@/* 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 */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified Comment(s), fixed */ +@/* GNU assembly comment, */ +@/* cleaned up whitespace, */ +@/* resulting in version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_initialize_low_level(VOID) +@{ + .global _tx_initialize_low_level + .thumb_func +_tx_initialize_low_level: +@ +@ /* Disable interrupts during ThreadX initialization. */ +@ + CPSID i +@ +@ /* Set base of available memory to end of non-initialised RAM area. */ +@ + LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer + LDR r1, =__RAM_segment_used_end__ @ Build first free address + ADD r1, r1, #4 @ + STR r1, [r0] @ Setup first unused memory pointer +@ +@ /* Setup Vector Table Offset Register. */ +@ + MOV r0, #0xE000E000 @ Build address of NVIC registers + LDR r1, =_vectors @ Pickup address of vector table + STR r1, [r0, #0xD08] @ Set vector table address +@ +@ /* 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 +@ +@ /* 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 +@ +@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ +@ + MOV r0, #0xE000E000 @ Build address of NVIC registers + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] @ Setup SysTick Reload Value + MOV r1, #0x7 @ Build SysTick Control Enable Value + STR r1, [r0, #0x10] @ Setup SysTick Control +@ +@ /* Configure handler priorities. */ +@ + LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers + + LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers + @ Note: SVC must be lowest priority, which is 0xFF + + LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers + @ Note: PnSV must be lowest priority, which is 0xFF + +@ +@ /* Return to caller. */ +@ + BX lr +@} +@ + +@/* Define shells for each of the unused vectors. */ +@ + .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} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter @ Call the ISR enter function +#endif + +@ /* Do interrupt handler work here */ +@ /* BL .... */ + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif + POP {r0, lr} + BX LR +@ } + +@ /* System Tick timer interrupt handler */ + .global __tx_SysTickHandler + .global SysTick_Handler + .thumb_func +__tx_SysTickHandler: + .thumb_func +SysTick_Handler: +@ VOID TimerInterruptHandler (VOID) +@ { +@ + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter @ Call the ISR enter function +#endif + BL _tx_timer_interrupt +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif + POP {r0, lr} + BX LR +@ } + + +@ /* NMI, DBG handlers */ + .global __tx_NMIHandler + .thumb_func +__tx_NMIHandler: + B __tx_NMIHandler + + .global __tx_DBGHandler + .thumb_func +__tx_DBGHandler: + B __tx_DBGHandler diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_context_restore.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_context_restore.S new file mode 100644 index 00000000..6dfd19df --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_context_restore.S @@ -0,0 +1,89 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_thread_system_stack_ptr + .global _tx_thread_execute_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_thread_preempt_disable + .global _tx_execution_isr_exit +@ +@ + .text + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_restore Cortex-M4/GNU */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, 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. */ +@/* This function restores the interrupt context if it is processing a */ +@/* nested interrupt. If not, it returns to the interrupt thread if no */ +@/* preemption is necessary. Otherwise, if preemption is necessary or */ +@/* if no thread was running, the function returns to the scheduler. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling routine */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs Interrupt Service Routines */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified comment(s), */ +@/* resulting in version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_restore(VOID) +@{ + .global _tx_thread_context_restore + .thumb_func +_tx_thread_context_restore: +@ +@ /* Not needed for this port - just return! */ + BX lr +@} diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_context_save.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_context_save.S new file mode 100644 index 00000000..e086d467 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_context_save.S @@ -0,0 +1,84 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_execution_isr_enter +@ +@ + .text + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_save Cortex-M4/GNU */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, 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. */ +@/* This function saves the context of an executing thread in the */ +@/* beginning of interrupt processing. The function also ensures that */ +@/* the system stack is used upon return to the calling ISR. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 Scott Larson Modified comment(s), and */ +@/* cleaned up whitespace, */ +@/* resulting in version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_save(VOID) +@{ + .global _tx_thread_context_save + .thumb_func +_tx_thread_context_save: +@ +@ /* Not needed for this port - just return! */ + BX lr +@} diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S new file mode 100644 index 00000000..4e6ec582 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S @@ -0,0 +1,83 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ + + +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ + + + .text 32 + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_interrupt_control Cortex-M4/GNU */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is responsible for changing the interrupt lockout */ +@/* posture of the system. */ +@/* */ +@/* INPUT */ +@/* */ +@/* new_posture New interrupt lockout posture */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* old_posture Old interrupt lockout posture */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* Application Code */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified comment(s), */ +@/* resulting in version 6.1 */ +@/* */ +@/**************************************************************************/ +@/* UINT _tx_thread_interrupt_control(UINT new_posture) +{ */ + .global _tx_thread_interrupt_control + .thumb_func +_tx_thread_interrupt_control: + +@/* Pickup current interrupt lockout posture. */ + + MRS r1, PRIMASK @ Pickup current interrupt lockout + +@/* Apply the new interrupt posture. */ + + MSR PRIMASK, r0 @ Apply the new interrupt lockout + MOV r0, r1 @ Transfer old to return register + BX lr @ Return to caller + +@/* } */ diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_schedule.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_schedule.S new file mode 100644 index 00000000..47d5e3e9 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_schedule.S @@ -0,0 +1,307 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the 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_system_stack_ptr + .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-M4/GNU */ +@/* 6.1.5 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function waits for a thread control block pointer to appear in */ +@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +@/* in the variable, the corresponding thread is resumed. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_initialize_kernel_enter ThreadX entry function */ +@/* _tx_thread_system_return Return to system from thread */ +@/* _tx_thread_context_restore Restore thread's context */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified comment(s), */ +@/* resulting in version 6.1 */ +@/* 03-02-2021 Scott Larson Modified comment(s), add */ +@/* low power code, */ +@/* resulting in version 6.1.5 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_schedule(VOID) +@{ + .global _tx_thread_schedule + .thumb_func +_tx_thread_schedule: +@ +@ /* This function should only ever be called on Cortex-M4 +@ from the first schedule request. Subsequent scheduling occurs +@ from the PendSV handling routines 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 TX_ENABLE_FPU_SUPPORT + 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 switch-out switch-in handler... Note that this handler is +@ common for both PendSV and SVCall. */ +@ + .global PendSV_Handler + .global __tx_PendSVHandler + .thumb_func +PendSV_Handler: + .thumb_func +__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 TX_ENABLE_FPU_SUPPORT + 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! */ +@ + 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/r1 + BL _tx_execution_thread_enter @ Call the thread execution enter function + POP {r0, r1} @ Recover r3 +#endif +@ +@ /* Restore the thread context and PSP. */ +@ + LDR r12, [r1, #8] @ Pickup thread's stack pointer + LDMIA r12!, {LR} @ Pickup LR +#ifdef TX_ENABLE_FPU_SUPPORT + 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 + +#ifdef TX_ENABLE_FPU_SUPPORT + + .global tx_thread_fpu_enable + .thumb_func +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 + + .global tx_thread_fpu_disable + .thumb_func +tx_thread_fpu_disable: +@ +@ /* Automatic VPF logic is supported, this function is present only for +@ backward compatibility purposes and therefore simply returns. */ +@ + BX LR @ Return to caller + +#endif diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_stack_build.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_stack_build.S new file mode 100644 index 00000000..c0e8bca9 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_stack_build.S @@ -0,0 +1,141 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the 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 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_stack_build Cortex-M4/GNU */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function builds a stack frame on the supplied thread's stack. */ +@/* The stack frame results in a fake interrupt return to the supplied */ +@/* function pointer. */ +@/* */ +@/* INPUT */ +@/* */ +@/* thread_ptr Pointer to thread control blk */ +@/* function_ptr Pointer to return function */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_thread_create Create thread service */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified Comment(s), setting */ +@/* R10 to top of stack is not */ +@/* needed. Removed references */ +@/* to stack frame, clean up */ +@/* whitespace, resulting */ +@/* in version 6.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-M4 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, #24] @ Store initial r9 + STR r3, [r2, #28] @ Store initial r10 + STR r3, [r2, #32] @ Store initial r11 +@ +@ /* Hardware stack follows. */ +@ + STR r3, [r2, #36] @ Store initial r0 + STR r3, [r2, #40] @ Store initial r1 + STR r3, [r2, #44] @ Store initial r2 + STR r3, [r2, #48] @ Store initial r3 + STR r3, [r2, #52] @ Store initial r12 + MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value + STR r3, [r2, #56] @ Store initial lr + STR r1, [r2, #60] @ Store initial pc + MOV r3, #0x01000000 @ Only T-bit need be set + STR r3, [r2, #64] @ Store initial xPSR +@ +@ /* Setup stack pointer. */ +@ thread_ptr -> tx_thread_stack_ptr = r2; +@ + STR r2, [r0, #8] @ Save stack pointer in thread's + @ control block + BX lr @ Return to caller +@} diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_system_return.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_system_return.S new file mode 100644 index 00000000..1a799fd4 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_thread_system_return.S @@ -0,0 +1,90 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ + + + .text 32 + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_system_return Cortex-M4/GNU */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is target processor specific. It is used to transfer */ +@/* control from a thread back to the 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 */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified comment(s), */ +@/* resulting in version 6.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 + 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 + +@/* } */ diff --git a/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_timer_interrupt.S b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_timer_interrupt.S new file mode 100644 index 00000000..35923a33 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/gnu/src/tx_timer_interrupt.S @@ -0,0 +1,259 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Timer */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@ + .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-M4/GNU */ +@/* 6.1 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function processes the hardware timer interrupt. This */ +@/* processing includes incrementing the system clock and checking for */ +@/* time slice and/or timer expiration. If either is found, the */ +@/* interrupt context save/restore functions are called along with the */ +@/* expiration functions. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_timer_expiration_process Timer expiration processing */ +@/* _tx_thread_time_slice Time slice interrupted thread */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* interrupt vector */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +@/* 09-30-2020 William E. Lamie Modified comment(s), */ +@/* resulting in version 6.1 */ +@/* */ +@/**************************************************************************/ +@VOID _tx_timer_interrupt(VOID) +@{ + .global _tx_timer_interrupt + .thumb_func +_tx_timer_interrupt: +@ +@ /* Upon entry to this routine, it is assumed that context save has already +@ been called, and therefore 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 + CMP r2, #0 @ Is it non-active? + BEQ __tx_timer_no_time_slice @ 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) +@ + CMP r2, #0 @ Has it expired? + BNE __tx_timer_no_time_slice @ 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 + CMP r2, #0 @ Is there anything in the list? + BEQ __tx_timer_no_timer @ 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 + CMP r2, #0 @ Did a time-slice expire? + BNE __tx_something_expired @ 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 + CMP r0, #0 @ Did a timer expire? + BEQ __tx_timer_nothing_expired @ 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 + CMP r0, #0 @ Check for timer expiration + BEQ __tx_timer_dont_activate @ 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 + CMP r2, #0 @ See if the flag is set + BEQ __tx_timer_not_ts_expiration @ 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 +@ +@} diff --git a/3rd_party/threadx/stm32f4xx_iar/tx_port.h b/3rd_party/threadx/ports/cortex_m4/iar/inc/tx_port.h similarity index 52% rename from 3rd_party/threadx/stm32f4xx_iar/tx_port.h rename to 3rd_party/threadx/ports/cortex_m4/iar/inc/tx_port.h index d5a6aad8..2796707c 100644 --- a/3rd_party/threadx/stm32f4xx_iar/tx_port.h +++ b/3rd_party/threadx/ports/cortex_m4/iar/inc/tx_port.h @@ -1,23 +1,11 @@ /**************************************************************************/ /* */ -/* Copyright (c) 1996-2017 by Express Logic Inc. */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ /* */ -/* This software is copyrighted by and is the sole property of Express */ -/* Logic, Inc. All rights, title, ownership, or other interests */ -/* in the software remain the property of Express Logic, Inc. This */ -/* software may only be used in accordance with the corresponding */ -/* license agreement. Any unauthorized use, duplication, transmission, */ -/* distribution, or disclosure of this software is expressly forbidden. */ -/* */ -/* This Copyright notice may not be removed or modified without prior */ -/* written consent of Express Logic, Inc. */ -/* */ -/* Express Logic, Inc. reserves the right to modify this software */ -/* without notice. */ -/* */ -/* Express Logic, Inc. info@expresslogic.com */ -/* 11423 West Bernardo Court http://www.expresslogic.com */ -/* San Diego, CA 92127 */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ /* */ /**************************************************************************/ @@ -38,11 +26,11 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* tx_port.h Cortex-M4/IAR */ -/* 5.6 */ +/* 6.1.6 */ /* */ /* AUTHOR */ /* */ -/* William E. Lamie, Express Logic, Inc. */ +/* William E. Lamie, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ @@ -59,40 +47,10 @@ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 10-10-2010 William E. Lamie Initial Cortex-M4 IAR */ -/* Support Version 5.0 */ -/* 07-15-2011 William E. Lamie Modified comment(s), added */ -/* IAR thread-safe library */ -/* support, and updated */ -/* version string, resulting */ -/* in version 5.1 */ -/* 04-15-2012 William E. Lamie Modified comment(s), added */ -/* FPU enable/disable function */ -/* prototypes, and updated */ -/* version string, resulting */ -/* in version 5.2 */ -/* 01-01-2014 William E. Lamie Modified comment(s), added */ -/* FPU enable/disable struct */ -/* member, and updated */ -/* version string, resulting */ -/* in version 5.3 */ -/* 04-15-2014 William E. Lamie Modified comment(s), and */ -/* updated version string, */ -/* resulting in version 5.4 */ -/* 09-01-2014 William E. Lamie Modified comment(s), and */ -/* updated version string, */ -/* resulting in version 5.5 */ -/* 06-01-2017 William E. Lamie Modified comment(s), added */ -/* support for new thread-safe */ -/* IAR libraries, removed */ -/* unneeded VFP enable flag, */ -/* added logic to remove the */ -/* need for context */ -/* save/restore calls in ISRs, */ -/* modified code for MISRA */ -/* compliance, and updated */ -/* version string, resulting */ -/* in version 5.6 */ +/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */ +/* macro definition, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -133,8 +91,6 @@ typedef unsigned long ULONG; typedef short SHORT; typedef unsigned short USHORT; -/*enable execution profile*/ -#define TX_ENABLE_EXECUTION_CHANGE_NOTIFY /* Define the priority levels for ThreadX. Legal values range from 32 to 1024 and MUST be evenly divisible by 32. */ @@ -164,7 +120,7 @@ typedef unsigned short USHORT; #endif -/* Define various constants for the ThreadX Cortex-M3 port. */ +/* Define various constants for the ThreadX ARM Cortex-M port. */ #define TX_INT_DISABLE 1 /* Disable interrupts */ #define TX_INT_ENABLE 0 /* Enable interrupts */ @@ -285,9 +241,119 @@ void __iar_Initlocks(void); #define TX_THREAD_CREATE_EXTENSION(thread_ptr) #define TX_THREAD_DELETE_EXTENSION(thread_ptr) #endif + + +#ifdef __ARMVFP__ + +#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); + +#endif + +/* 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(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_CONTROL(_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(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_CONTROL(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = __get_CONTROL(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + __asm volatile ("vmov.f32 s0, s0"); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = __get_CONTROL(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + __set_CONTROL(_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 + #define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) #define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) +#endif + /* Define the ThreadX object creation extensions for the remaining objects. */ @@ -345,9 +411,8 @@ ULONG _tx_misra_ipsr_get(VOID); #ifndef TX_DISABLE_INLINE -#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \ - b = (UINT) __CLZ(m); \ - b = 31 - b; +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT)__CLZ(__RBIT((m))); + #endif @@ -415,7 +480,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "Copyright (c) 1996-2017 Express Logic Inc. * ThreadX Cortex-M4/IAR Version G5.8.5.6 SN: X-WARE_PLATFORM_STM32F4_DISCOVERY_EVALUATION_VERSION_08-01-2017 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/IAR Version 6.1.6 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/3rd_party/threadx/ports/cortex_m4/iar/readme_threadx.txt b/3rd_party/threadx/ports/cortex_m4/iar/readme_threadx.txt new file mode 100644 index 00000000..f32b889b --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/readme_threadx.txt @@ -0,0 +1,230 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M4 + + Using the IAR 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-M4 simulator. + + +3. System Initialization + +The entry point in ThreadX for the Cortex-M4 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-M4 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-M4 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 {lr} + + ; ISR processing goes here, including any needed function calls. + + POP {lr} + BX lr + + +7. IAR Thread-safe Library Support + +Thread-safe support for the IAR tools is easily enabled by building the ThreadX library +and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file +should have the following line added (if not already in place): + +initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application + + +7. IAR Thread-safe Library Support + +Thread-safe support for the IAR tools is easily enabled by building the ThreadX library +and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file +should have the following line added (if not already in place): + +initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application + +The project options "General Options -> Library Configuration" should also have the +"Enable thread support in library" box selected. + + +8. VFP Support + +ThreadX for Cortex-M4 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: + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_thread_schedule.s Added low power feature + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using IAR's ARM tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_iar.c b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_iar.c new file mode 100644 index 00000000..5eabedec --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_iar.c @@ -0,0 +1,804 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** IAR Multithreaded Library Support */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Define IAR library for tools prior to version 8. */ + +#if (__VER__ < 8000000) + + +/* IAR version 7 and below. */ + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/* This implementation requires that the following macros are defined in the + tx_port.h file and is included with the following code segments: + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#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 + + +#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 is included with the following code segments: + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#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 + + +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 /* Added to get access to FOPEN_MAX */ +#ifndef _MAX_FLOCK +#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */ +#endif + + +TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK]; +UINT __tx_iar_file_lock_next_free_mutex = 0; + + +/* Define error counters, just for debug purposes. */ + +UINT __tx_iar_file_lock_no_mutexes; +UINT __tx_iar_file_lock_internal_errors; +UINT __tx_iar_file_lock_isr_caller; + + +void __iar_file_Mtxinit(__iar_Rmtx *m) +{ + +UINT i; +UINT status; +TX_MUTEX *mutex_ptr; + + + /* First, find a free mutex in the list. */ + for (i = 0; i < _MAX_FLOCK; i++) + { + + /* Setup a pointer to the start of the next free mutex. */ + mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; + + /* Check for wrap-around on the next free mutex. */ + if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + { + + /* Yes, set the free index back to 0. */ + __tx_iar_file_lock_next_free_mutex = 0; + } + + /* Is this mutex free? */ + if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Yes, this mutex is free, get out of the loop! */ + break; + } + } + + /* Determine if a free mutex was found. */ + if (i >= _MAX_LOCK) + { + + /* Error! No more free mutexes! */ + + /* Increment the no mutexes error counter. */ + __tx_iar_file_lock_no_mutexes++; + + /* Set return pointer to NULL. */ + *m = TX_NULL; + + /* Return. */ + return; + } + + /* Now create the ThreadX mutex for the IAR library. */ + status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT); + + /* Determine if the creation was successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, successful creation, return mutex pointer. */ + *m = (VOID *) mutex_ptr; + } + else + { + + /* Increment the internal error counter. */ + __tx_iar_file_lock_internal_errors++; + + /* Return a NULL pointer to indicate an error. */ + *m = TX_NULL; + } +} + +void __iar_file_Mtxdst(__iar_Rmtx *m) +{ + + /* Simply delete the mutex. */ + _tx_mutex_delete((TX_MUTEX *) *m); +} + +void __iar_file_Mtxlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex locks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Get the mutex. */ + status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_file_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_file_lock_isr_caller++; + } +} + +void __iar_file_Mtxunlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex unlocks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Release the mutex. */ + status = _tx_mutex_put((TX_MUTEX *) *m); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_file_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_file_lock_isr_caller++; + } +} +#endif /* _DLIB_FILE_DESCRIPTOR */ + +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#endif /* IAR version 8 and above. */ diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_initialize_low_level.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_initialize_low_level.s new file mode 100644 index 00000000..4f107ea6 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_initialize_low_level.s @@ -0,0 +1,165 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/IAR */ +;/* 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) +;{ + PUBLIC _tx_initialize_low_level +_tx_initialize_low_level: +; +; /* Ensure that interrupts are disabled. */ +; + CPSID i ; Disable interrupts +; +; +; /* 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 +; +; /* 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, =__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 +; +; /* Configure SysTick. */ +; + MOV r0, #0xE000E000 ; Build address of NVIC registers + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] ; Setup SysTick Reload Value + MOV r1, #0x7 ; Build SysTick Control Enable Value + STR r1, [r0, #0x10] ; Setup SysTick Control +; +; /* Configure handler priorities. */ +; + LDR r1, =0x00000000 ; Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] ; Setup System Handlers 4-7 Priority Registers + + LDR r1, =0xFF000000 ; SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] ; Setup System Handlers 8-11 Priority Registers + ; Note: SVC must be lowest priority, which is 0xFF + + LDR r1, =0x40FF0000 ; SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] ; Setup System Handlers 12-15 Priority Registers + ; Note: PnSV must be lowest priority, which is 0xFF +; +; /* Return to caller. */ +; + BX lr +;} +; + PUBLIC SysTick_Handler + PUBLIC __tx_SysTickHandler +__tx_SysTickHandler: +SysTick_Handler: +; +; VOID SysTick_Handler(VOID) +; { +; + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter ; Call the ISR enter function +#endif + BL _tx_timer_interrupt +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit ; Call the ISR exit function +#endif + POP {r0, lr} + BX LR +; } + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_misra.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_misra.s new file mode 100644 index 00000000..900ffbe7 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_misra.s @@ -0,0 +1,1074 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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_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, 35H, 2EH, 38H + 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 + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** 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 + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_pointer_to_ulong_convert: + 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_ulong_to_pointer_convert(ULONG input); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ulong_to_pointer_convert: + 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: + ADDS R2,R0,#+8 + SUBS R2,R2,R0 + RSBS R2,R2,#+0 + ADD R0,R0,R2 + 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 + + +/******************************************************************************************/ +/******************************************************************************************/ +/** */ +/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */ +/** */ +/******************************************************************************************/ +/******************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_indirect_void_to_uchar_pointer_convert: + BX LR ;; return + + +/***************************************************************************************/ +/***************************************************************************************/ +/** */ +/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */ +/** */ +/***************************************************************************************/ +/***************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_indirect_uchar_pointer_convert: + BX LR ;; return + + +/***********************************************************************************/ +/***********************************************************************************/ +/** */ +/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */ +/** */ +/***********************************************************************************/ +/***********************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_block_pool_to_uchar_pointer_convert: + BX LR ;; return + + +/******************************************************************************************/ +/******************************************************************************************/ +/** */ +/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */ +/** */ +/******************************************************************************************/ +/******************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_block_pool_pointer_convert: + BX LR ;; return + + +/*****************************************************************************/ +/*****************************************************************************/ +/** */ +/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */ +/** */ +/*****************************************************************************/ +/*****************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_uchar_pointer_convert: + BX LR ;; return + + +/************************************************************************************/ +/************************************************************************************/ +/** */ +/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */ +/** */ +/************************************************************************************/ +/************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_block_pool_pointer_convert: + BX LR ;; return + + +/**************************************************************************************/ +/**************************************************************************************/ +/** */ +/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */ +/** */ +/**************************************************************************************/ +/**************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_indirect_uchar_pointer_convert: + BX LR ;; return + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/** */ +/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */ +/** */ +/*****************************************************************************************/ +/*****************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_byte_pool_pointer_convert: + BX LR ;; return + + +/***************************************************************************************/ +/***************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */ +/** */ +/***************************************************************************************/ +/***************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_byte_pool_to_uchar_pointer_convert: + BX LR ;; return + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/** */ +/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */ +/** */ +/*****************************************************************************************/ +/*****************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_align_type_pointer_convert: + BX LR ;; return + + +/****************************************************************************************************/ +/****************************************************************************************************/ +/** */ +/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */ +/** */ +/****************************************************************************************************/ +/****************************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_indirect_byte_pool_pointer_convert: + BX LR ;; return + + +/**************************************************************************************************/ +/**************************************************************************************************/ +/** */ +/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */ +/** */ +/**************************************************************************************************/ +/**************************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_event_flags_pointer_convert: + BX LR ;; return + + +/*****************************************************************************/ +/*****************************************************************************/ +/** */ +/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */ +/** */ +/*****************************************************************************/ +/*****************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_ulong_pointer_convert: + BX LR ;; return + + +/********************************************************************************/ +/********************************************************************************/ +/** */ +/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */ +/** */ +/********************************************************************************/ +/********************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_mutex_pointer_convert: + 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 + + +/********************************************************************************/ +/********************************************************************************/ +/** */ +/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */ +/** */ +/********************************************************************************/ +/********************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_queue_pointer_convert: + BX LR ;; return + + +/****************************************************************************************/ +/****************************************************************************************/ +/** */ +/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */ +/** */ +/****************************************************************************************/ +/****************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_semaphore_pointer_convert: + BX LR ;; return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_void_pointer_convert: + BX LR ;; return + + +/*********************************************************************************/ +/*********************************************************************************/ +/** */ +/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */ +/** */ +/*********************************************************************************/ +/*********************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ulong_to_thread_pointer_convert: + BX LR ;; return + + +/***************************************************************************************************/ +/***************************************************************************************************/ +/** */ +/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */ +/** */ +/***************************************************************************************************/ +/***************************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_timer_indirect_to_void_pointer_convert: + BX LR ;; return + + +/***************************************************************************************/ +/***************************************************************************************/ +/** */ +/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */ +/** */ +/***************************************************************************************/ +/***************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_const_char_to_char_pointer_convert: + BX LR ;; return + + +/**********************************************************************************/ +/**********************************************************************************/ +/** */ +/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */ +/** */ +/**********************************************************************************/ +/**********************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_void_to_thread_pointer_convert: + BX LR ;; return + + +#ifdef TX_ENABLE_EVENT_TRACE + +/************************************************************************************************/ +/************************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */ +/** */ +/************************************************************************************************/ +/************************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_object_to_uchar_pointer_convert: + BX LR ;; return + + +/************************************************************************************************/ +/************************************************************************************************/ +/** */ +/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */ +/** */ +/************************************************************************************************/ +/************************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_object_pointer_convert: + BX LR ;; return + + +/******************************************************************************************/ +/******************************************************************************************/ +/** */ +/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */ +/** */ +/******************************************************************************************/ +/******************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_header_pointer_convert: + BX LR ;; return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_to_entry_pointer_convert: + BX LR ;; return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_entry_to_uchar_pointer_convert: + BX LR ;; return +#endif + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_char_to_uchar_pointer_convert: + BX LR ;; return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_ipsr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ipsr_get: + MRS R0, IPSR + BX LR ;; return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_control_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_control_get: + MRS R0, CONTROL + BX LR ;; return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_control_set(ULONG value); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_control_set: + MSR CONTROL, R0 + BX LR ;; return + + +#ifdef __ARMVFP__ + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_fpccr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(2) + THUMB +_tx_misra_fpccr_get: + LDR r0, =0xE000EF34 ; Build FPCCR address + LDR r0, [r0] ; Load FPCCR value + BX LR ;; return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_vfp_touch(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_vfp_touch: + vmov.f32 s0, s0 + BX LR ;; return + +#endif + + + SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA + DC32 0 + + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_context_restore.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_context_restore.s new file mode 100644 index 00000000..850fefa9 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_context_restore.s @@ -0,0 +1,89 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + EXTERN _tx_execution_isr_exit +; +; + SECTION `.text`:CODE:NOROOT(2) + THUMB +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_context_restore Cortex-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, 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. */ +;/* This function restores the interrupt context if it is processing a */ +;/* nested interrupt. If not, it returns to the interrupt thread if no */ +;/* preemption is necessary. Otherwise, if preemption is necessary or */ +;/* if no thread was running, the function returns to the scheduler. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* [_tx_execution_isr_exit] Execution profiling ISR exit */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ISRs Interrupt Service Routines */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_context_restore(VOID) +;{ + PUBLIC _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} ; Save return address +#endif +; + POP {lr} + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_context_save.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_context_save.s new file mode 100644 index 00000000..46cc01d0 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_context_save.s @@ -0,0 +1,87 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + EXTERN _tx_execution_isr_enter +; +; + SECTION `.text`:CODE:NOROOT(2) + THUMB +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_context_save Cortex-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, 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. */ +;/* This function saves the context of an executing thread in the */ +;/* beginning of interrupt processing. The function also ensures that */ +;/* the system stack is used upon return to the calling ISR. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ISRs */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_context_save(VOID) +;{ + PUBLIC _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 +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_control.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_control.s new file mode 100644 index 00000000..c903f17b --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_control.s @@ -0,0 +1,74 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + SECTION `.text`:CODE:NOROOT(2) + THUMB +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_interrupt_control Cortex-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for changing the interrupt lockout */ +;/* posture of the system. */ +;/* */ +;/* INPUT */ +;/* */ +;/* new_posture New interrupt lockout posture */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* old_posture Old interrupt lockout posture */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;UINT _tx_thread_interrupt_control(UINT new_posture) +;{ + PUBLIC _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 +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_disable.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_disable.s new file mode 100644 index 00000000..5577555c --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_disable.s @@ -0,0 +1,76 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for disabling interrupts and returning */ +;/* the previous interrupt lockout posture. */ +;/* */ +;/* INPUT */ +;/* */ +;/* old_posture Old interrupt lockout posture */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;UINT _tx_thread_interrupt_disable(UINT new_posture) +;{ + PUBLIC _tx_thread_interrupt_disable +_tx_thread_interrupt_disable: +; +; /* Return current interrupt lockout posture. */ +; + MRS r0, PRIMASK + CPSID i + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_restore.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_restore.s new file mode 100644 index 00000000..10baa764 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_interrupt_restore.s @@ -0,0 +1,75 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + SECTION `.text`:CODE:NOROOT(2) + THUMB +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_interrupt_restore Cortex-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for restoring the previous */ +;/* interrupt lockout posture. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* previous_posture Previous interrupt posture */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_interrupt_restore(UINT new_posture) +;{ + PUBLIC _tx_thread_interrupt_restore +_tx_thread_interrupt_restore: +; +; /* Restore previous interrupt lockout posture. */ +; + MSR PRIMASK, r0 + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_schedule.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_schedule.s new file mode 100644 index 00000000..45008ba3 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_schedule.s @@ -0,0 +1,302 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + EXTERN _tx_thread_current_ptr + EXTERN _tx_thread_execute_ptr + EXTERN _tx_timer_time_slice + EXTERN _tx_thread_system_stack_ptr + EXTERN _tx_execution_thread_enter + EXTERN _tx_execution_thread_exit + EXTERN _tx_thread_preempt_disable +#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-M4/IAR */ +;/* 6.1.5 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function waits for a thread control block pointer to appear in */ +;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +;/* in the variable, the corresponding thread is resumed. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* _tx_initialize_kernel_enter ThreadX entry function */ +;/* _tx_thread_system_return Return to system from thread */ +;/* _tx_thread_context_restore Restore thread's context */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* 03-02-2021 Scott Larson Modified comment(s), add */ +;/* low power code, */ +;/* resulting in version 6.1.5 */ +;/* */ +;/**************************************************************************/ +;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 routines 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 PendSV handler. */ +; + PUBLIC PendSV_Handler + PUBLIC __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 + MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address + MOV32 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 + MOV32 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! */ +; + 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 + MOV32 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/r1 + BL _tx_execution_thread_enter ; Call the thread execution enter function + POP {r0, r1} ; Recover r3 +#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: + 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 +;} +; +#ifdef __ARMVFP__ + + PUBLIC 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 + + PUBLIC tx_thread_fpu_disable +tx_thread_fpu_disable: +; +; /* Automatic VPF logic is supported, this function is present only for +; backward compatibility purposes and therefore simply returns. */ +; + BX LR ; Return to caller + +#endif + + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_stack_build.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_stack_build.s new file mode 100644 index 00000000..493ee69d --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_stack_build.s @@ -0,0 +1,134 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function builds a stack frame on the supplied thread's stack. */ +;/* The stack frame results in a fake interrupt return to the supplied */ +;/* function pointer. */ +;/* */ +;/* INPUT */ +;/* */ +;/* thread_ptr Pointer to thread control blk */ +;/* function_ptr Pointer to return function */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* _tx_thread_create Create thread service */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +;{ + PUBLIC _tx_thread_stack_build +_tx_thread_stack_build: +; +; +; /* Build a fake interrupt frame. The form of the fake interrupt stack +; on the Cortex-M should look like the following after it is built: +; +; Stack Top: +; LR Interrupted LR (LR at time of PENDSV) +; r4 Initial value for r4 +; r5 Initial value for r5 +; r6 Initial value for r6 +; r7 Initial value for r7 +; r8 Initial value for r8 +; r9 Initial value for r9 +; r10 Initial value for r10 +; r11 Initial value for r11 +; r0 Initial value for r0 (Hardware stack starts here!!) +; r1 Initial value for r1 +; r2 Initial value for r2 +; r3 Initial value for r3 +; r12 Initial value for r12 +; lr Initial value for lr +; pc Initial value for pc +; xPSR Initial value for xPSR +; +; Stack Bottom: (higher memory address) */ +; + LDR r2, [r0, #16] ; Pickup end of stack area + BIC r2, r2, #0x7 ; Align frame for 8-byte alignment + SUB r2, r2, #68 ; Subtract frame size + LDR r3, =0xFFFFFFFD ; Build initial LR value + STR r3, [r2, #0] ; Save on the stack +; +; /* Actually build the stack frame. */ +; + MOV r3, #0 ; Build initial register value + STR r3, [r2, #4] ; Store initial r4 + STR r3, [r2, #8] ; Store initial r5 + STR r3, [r2, #12] ; Store initial r6 + STR r3, [r2, #16] ; Store initial r7 + STR r3, [r2, #20] ; Store initial r8 + STR r3, [r2, #24] ; Store initial r9 + STR r3, [r2, #28] ; Store initial r10 + STR r3, [r2, #32] ; Store initial r11 +; +; /* Hardware stack follows. */ +; + STR r3, [r2, #36] ; Store initial r0 + STR r3, [r2, #40] ; Store initial r1 + STR r3, [r2, #44] ; Store initial r2 + STR r3, [r2, #48] ; Store initial r3 + STR r3, [r2, #52] ; Store initial r12 + MOV r3, #0xFFFFFFFF ; Poison EXC_RETURN value + STR r3, [r2, #56] ; Store initial lr + STR r1, [r2, #60] ; Store initial pc + MOV r3, #0x01000000 ; Only T-bit need be set + STR r3, [r2, #64] ; Store initial xPSR +; +; /* Setup stack pointer. */ +; thread_ptr -> tx_thread_stack_ptr = r2; +; + STR r2, [r0, #8] ; Save stack pointer in thread's + ; control block + BX lr ; Return to caller +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_system_return.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_system_return.s new file mode 100644 index 00000000..4ea6aa72 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_thread_system_return.s @@ -0,0 +1,87 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + SECTION `.text`:CODE:NOROOT(2) + THUMB +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_system_return Cortex-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is target processor specific. It is used to transfer */ +;/* control from a thread back to the ThreadX system. Only a */ +;/* minimal context is saved since the compiler assumes temp registers */ +;/* are going to get slicked by a function call anyway. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_thread_schedule Thread scheduling loop */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ThreadX components */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_system_return(VOID) +;{ + PUBLIC _tx_thread_system_return +_tx_thread_system_return??rA: +_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 +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/iar/src/tx_timer_interrupt.s b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_timer_interrupt.s new file mode 100644 index 00000000..dabf7e1c --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/iar/src/tx_timer_interrupt.s @@ -0,0 +1,256 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/IAR */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function processes the hardware timer interrupt. This */ +;/* processing includes incrementing the system clock and checking for */ +;/* time slice and/or timer expiration. If either is found, the */ +;/* expiration functions are called. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_timer_expiration_process Timer expiration processing */ +;/* _tx_thread_time_slice Time slice interrupted thread */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* interrupt vector */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_timer_interrupt(VOID) +;{ + PUBLIC _tx_timer_interrupt +_tx_timer_interrupt: +; +; /* Upon entry to this routine, it is assumed that the compiler scratch registers are available +; for use. */ +; +; /* Increment the system clock. */ +; _tx_timer_system_clock++; +; + MOV32 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) +; { +; + MOV32 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? +; +; /* Set the time-slice expired flag. */ +; _tx_timer_expired_time_slice = TX_TRUE; +; + MOV32 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) +; { +; + MOV32 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; +; + MOV32 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) +; + MOV32 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; +; + MOV32 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)) +; { +; + MOV32 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 + MOV32 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) +; { +; + MOV32 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) +; { +; + MOV32 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 + MOV32 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 + MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address + LDR r1, [r0] ; Pickup the current thread pointer + MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address + LDR r3, [r2] ; Pickup the execute thread pointer + MOV32 r0, 0xE000ED04 ; Build address of control register + MOV32 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 +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/inc/tx_port.h b/3rd_party/threadx/ports/cortex_m4/keil/inc/tx_port.h new file mode 100644 index 00000000..19335f7a --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/inc/tx_port.h @@ -0,0 +1,474 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/Keil */ +/* 6.1.6 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, 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. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */ +/* macro definition, */ +/* resulting in version 6.1.6 */ +/* */ +/**************************************************************************/ + +#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 +#include + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 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-M3 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 + + +/* 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 +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) + + +#ifndef TX_MISRA_ENABLE + +register unsigned int _ipsr __asm("ipsr"); + +#endif + + +#ifdef __TARGET_FPU_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 + +#ifdef TX_SOURCE_CODE + +register ULONG _control __asm("control"); + +#endif +#endif + +/* 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 = _control; \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _control = _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 + +void _tx_vfp_access(void); + +#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 = _control; \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _control = _tx_vfp_state; \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _control; \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + _tx_vfp_access(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _control; \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _control = _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 + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif + + +/* 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 +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr) +#else +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif +#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++; + + +/* Determine if the ARM architecture has the CLZ instruction. This is available on + architectures v5 and above. If available, redefine the macro for calculating the + lowest bit set. */ + +#ifndef TX_DISABLE_INLINE + +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m))); + +#endif + + +/* Define ThreadX interrupt lockout and restore macros for protection on + access of critical kernel information. The restore interrupt macro must + restore the interrupt posture of the running thread prior to the value + present prior to the disable macro. In most cases, the save area macro + is used to define a local function save area for the disable and restore + macros. */ + +#ifdef TX_DISABLE_INLINE + +UINT _tx_thread_interrupt_disable(VOID); +VOID _tx_thread_interrupt_restore(UINT previous_posture); + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); + +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); + +#else + +#define TX_INTERRUPT_SAVE_AREA UINT was_masked; +#define TX_DISABLE was_masked = __disable_irq(); +#define TX_RESTORE if (was_masked == 0) __enable_irq(); + +#define _tx_thread_system_return _tx_thread_system_return_inline + + +static void _tx_thread_system_return_inline(void) +{ +unsigned int was_masked; + + + /* Set PendSV to invoke ThreadX scheduler. */ + *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + if (_ipsr == 0) + { + was_masked = __disable_irq(); + __enable_irq(); + if (was_masked != 0) + __disable_irq(); + } +} +#endif + + +/* Define FPU extension for the Cortex-M4. 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-M4/Keil Version 6.1.6 *"; +#else +#ifdef TX_MISRA_ENABLE +extern CHAR _tx_version_id[100]; +#else +extern CHAR _tx_version_id[]; +#endif +#endif + + +#endif + + + + diff --git a/3rd_party/threadx/ports/cortex_m4/keil/readme_threadx.txt b/3rd_party/threadx/ports/cortex_m4/keil/readme_threadx.txt new file mode 100644 index 00000000..e84f29c9 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/readme_threadx.txt @@ -0,0 +1,217 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M4 + + Thumb & 32-bit Mode + + Using the Keil Microcontroller Development Kit + +1. Building the ThreadX run-time Library + +Building the ThreadX library is easy, simply load the project file +ThreadX_Library.Uv2, which is located inside the "example_build" directory. + +Once the ThreadX library files are displayed in the project window, +select the "Build Target" operation and observe the compilation and assembly +of the ThreadX library. This project build produces the ThreadX library +file ThreadX_Library.lib. + + +2. Demonstration System + +The ThreadX demonstration is designed to execute under the Keil debugger or +Cortex-M4 hardware. This demonstration is slightly smaller than typical ThreadX +demonstrations, and thus requires less than 7KB of Flash and less than 4KB of RAM. + +Building the demonstration is easy; simply open the ThreadX demonstration +project file ThreadX_Demo.Uv2, which is located inside the "example_build" +directory. + +Once open, select the "Build Target" operation and observe the compilation of +sample_threadx.c (which is the demonstration application) and linking with +ThreadX_Library.lib. The resulting file sample_threadx.axf is a binary file that +can be downloaded and executed on Cortex-M4 hardware. + + +3. System Initialization + +The entry point in ThreadX for the Cortex-M4 using Keil tools is at label +__main. This is defined within the Keil 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-M4 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.Uv2 +project to debugging 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-M4 +targets. There are a certain set of requirements that are defined in the +following sub-sections: + + +6.1 Vector Area + +The Cortex-M4 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-M4 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: + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + tx_thread_schedule.s Fix compilation error + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_thread_schedule.s Added low power feature + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using Keil tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_initialize_low_level.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_initialize_low_level.s new file mode 100644 index 00000000..a16879b9 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_initialize_low_level.s @@ -0,0 +1,271 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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 */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +;#define TX_SOURCE_CODE +; +; +;/* Include necessary system files. */ +; +;#include "tx_api.h" +;#include "tx_initialize.h" +;#include "tx_thread.h" +;#include "tx_timer.h" +; +; + IMPORT _tx_thread_system_stack_ptr + IMPORT _tx_initialize_unused_memory + IMPORT _tx_thread_context_save + IMPORT _tx_thread_context_restore + IMPORT _tx_timer_interrupt + IMPORT __main + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$ZI$$Base| + IMPORT |Image$$ZI$$Limit| + IMPORT __tx_PendSVHandler +; +; +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 __tx_PendSVHandler ; PendSV + DCD __tx_SysTickHandler ; SysTick + 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 + IF {TARGET_FPU_VFP} = {TRUE} + 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-M4/AC5 */ +;/* 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) +;{ + EXPORT _tx_initialize_low_level +_tx_initialize_low_level +; +; /* Disable interrupts during ThreadX initialization. */ +; + CPSID i +; +; /* Set base of available memory to end of non-initialised RAM area. */ +; + LDR r0, =_tx_initialize_unused_memory ; Build address of unused memory pointer + LDR r1, =|Image$$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, =__tx_vectors ; Pickup address of vector table + STR r1, [r0, #0xD08] ; Set vector table address +; +; /* Enable the cycle count register. */ +; +; LDR r0, =0xE0001000 ; Build address of DWT register +; LDR r1, [r0] ; Pickup the current value +; ORR r1, r1, #1 ; Set the CYCCNTENA bit +; STR r1, [r0] ; Enable the cycle count register +; +; /* Set system stack pointer from vector value. */ +; + LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer + LDR r1, =__tx_vectors ; Pickup address of vector table + LDR r1, [r1] ; Pickup reset stack pointer + STR r1, [r0] ; Save system stack pointer +; +; /* Configure SysTick. */ +; + MOV r0, #0xE000E000 ; Build address of NVIC registers + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] ; Setup SysTick Reload Value + MOV r1, #0x7 ; Build SysTick Control Enable Value + STR r1, [r0, #0x10] ; Setup SysTick Control +; +; /* Configure handler priorities. */ +; + LDR r1, =0x00000000 ; Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] ; Setup System Handlers 4-7 Priority Registers + + LDR r1, =0xFF000000 ; SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] ; Setup System Handlers 8-11 Priority Registers + ; Note: SVC must be lowest priority, which is 0xFF + + LDR r1, =0x40FF0000 ; SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] ; Setup System Handlers 12-15 Priority Registers + ; Note: PnSV must be lowest priority, which is 0xFF +; +; /* Return to caller. */ +; + BX lr +;} +; +; +;/* Define 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} + +; /* Do interrupt handler work here */ +; /* .... */ + + POP {r0, lr} + BX LR +; } + + EXPORT __tx_SysTickHandler +__tx_SysTickHandler +; VOID TimerInterruptHandler (VOID) +; { +; + PUSH {r0, lr} + BL _tx_timer_interrupt + POP {r0, lr} + BX LR +; } + + EXPORT __tx_NMIHandler +__tx_NMIHandler + B __tx_NMIHandler + + EXPORT __tx_DBGHandler +__tx_DBGHandler + B __tx_DBGHandler + + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_context_restore.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_context_restore.s new file mode 100644 index 00000000..0ed36142 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_context_restore.s @@ -0,0 +1,91 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IMPORT _tx_execution_isr_exit + ENDIF +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_context_restore Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, 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. */ +;/* This function restores the interrupt context if it is processing a */ +;/* nested interrupt. If not, it returns to the interrupt thread if no */ +;/* preemption is necessary. Otherwise, if preemption is necessary or */ +;/* if no thread was running, the function returns to the scheduler. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_thread_schedule Thread scheduling routine */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ISRs Interrupt Service Routines */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_context_restore(VOID) +;{ + EXPORT _tx_thread_context_restore +_tx_thread_context_restore + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY +; +; /* Call the ISR exit function to indicate an ISR is complete. */ +; + PUSH {r0,lr} ; Save ISR lr + BL _tx_execution_isr_exit ; Call the ISR exit function + POP {r0,lr} ; Restore ISR lr + ENDIF +; + POP {lr} + BX lr +;} + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_context_save.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_context_save.s new file mode 100644 index 00000000..a6827883 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_context_save.s @@ -0,0 +1,91 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IMPORT _tx_execution_isr_enter + ENDIF +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_context_save Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, 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. */ +;/* This function saves the context of an executing thread in the */ +;/* beginning of interrupt processing. The function also ensures that */ +;/* the system stack is used upon return to the calling ISR. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ISRs */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_context_save(VOID) +;{ + EXPORT _tx_thread_context_save +_tx_thread_context_save + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY +; +; /* Call the ISR enter function to indicate an ISR is executing. */ +; + PUSH {r0, lr} ; Save ISR lr + BL _tx_execution_isr_enter ; Call the ISR enter function + POP {r0, lr} ; Recover ISR lr + ENDIF +; +; /* Return to interrupt processing. */ +; + BX lr ; Return to interrupt processing caller +;} + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_control.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_control.s new file mode 100644 index 00000000..ef983f17 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_control.s @@ -0,0 +1,76 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for changing the interrupt lockout */ +;/* posture of the system. */ +;/* */ +;/* INPUT */ +;/* */ +;/* new_posture New interrupt lockout posture */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* old_posture Old interrupt lockout posture */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;UINT _tx_thread_interrupt_control(UINT new_posture) +;{ + EXPORT _tx_thread_interrupt_control +_tx_thread_interrupt_control +; +; /* Pickup current interrupt lockout posture. */ +; + MRS r1, PRIMASK + MSR PRIMASK, r0 + MOV r0, r1 + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_disable.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_disable.s new file mode 100644 index 00000000..6d11e5b8 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_disable.s @@ -0,0 +1,75 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_interrupt_disable Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for disabling interrupts and returning */ +;/* the previous interrupt lockout posture. */ +;/* */ +;/* INPUT */ +;/* */ +;/* old_posture Old interrupt lockout posture */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;UINT _tx_thread_interrupt_disable(UINT new_posture) +;{ + EXPORT _tx_thread_interrupt_disable +_tx_thread_interrupt_disable +; +; /* Return current interrupt lockout posture. */ +; + MRS r0, PRIMASK + CPSID i + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_restore.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_restore.s new file mode 100644 index 00000000..0f52527b --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_interrupt_restore.s @@ -0,0 +1,74 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_interrupt_restore Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is responsible for restoring the previous */ +;/* interrupt lockout posture. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* previous_posture Previous interrupt posture */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application Code */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_thread_interrupt_restore(UINT new_posture) +;{ + EXPORT _tx_thread_interrupt_restore +_tx_thread_interrupt_restore +; +; /* Restore previous interrupt lockout posture. */ +; + MSR PRIMASK, r0 + BX lr +; +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_schedule.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_schedule.s new file mode 100644 index 00000000..a08a5478 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_schedule.s @@ -0,0 +1,308 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the 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 :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IMPORT _tx_execution_thread_enter + IMPORT _tx_execution_thread_exit + ENDIF + IF :DEF:TX_LOW_POWER + IMPORT tx_low_power_enter + IMPORT tx_low_power_exit + ENDIF +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_schedule Cortex-M4/AC5 */ +;/* 6.1.5 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function waits for a thread control block pointer to appear in */ +;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +;/* in the variable, the corresponding thread is resumed. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* _tx_initialize_kernel_enter ThreadX entry function */ +;/* _tx_thread_system_return Return to system from thread */ +;/* _tx_thread_context_restore Restore thread's context */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* 03-02-2021 Scott Larson Modified comment(s), add */ +;/* low power code, */ +;/* resulting in version 6.1.5 */ +;/* */ +;/**************************************************************************/ +;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 routines 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. */ +; + IF {TARGET_FPU_VFP} = {TRUE} + MRS r0, CONTROL ; Pickup current CONTROL register + BIC r0, r0, #4 ; Clear the FPCA bit + MSR CONTROL, r0 ; Setup new CONTROL register + ENDIF +; +; /* Enable the 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 :DEF: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 + MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address + MOV32 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 + IF {TARGET_FPU_VFP} = {TRUE} + 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 + MOV32 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! */ +; + 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 + MOV32 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 :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY +; +; /* Call the thread entry function to indicate the thread is executing. */ +; + PUSH {r0, r1} ; Save r0/r1 + BL _tx_execution_thread_enter ; Call the thread execution enter function + POP {r0, r1} ; Recover r3 + ENDIF +; +; /* Restore the thread context and PSP. */ +; + LDR r12, [r1, #8] ; Pickup thread's stack pointer + LDMIA r12!, {LR} ; Pickup LR + IF {TARGET_FPU_VFP} = {TRUE} + 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! + + IF :DEF:TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_enter ; Possibly enter low power mode + POP {r0-r3} + ENDIF + + IF :DEF:TX_ENABLE_WFI + DSB ; Ensure no outstanding memory transactions + WFI ; Wait for interrupt + ISB ; Ensure pipeline is flushed + ENDIF + + IF :DEF: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 + + IF {TARGET_FPU_VFP} = {TRUE} + EXPORT 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 + + EXPORT tx_thread_fpu_disable +tx_thread_fpu_disable +; +; /* Automatic VPF logic is supported, this function is present only for +; backward compatibility purposes and therefore simply returns. */ +; + BX LR ; Return to caller + + EXPORT _tx_vfp_access +_tx_vfp_access + VMOV.F32 s0, s0 ; Simply access the VFP + BX lr ; Return to caller + + ENDIF + + ALIGN + LTORG + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_stack_build.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_stack_build.s new file mode 100644 index 00000000..f548938b --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_stack_build.s @@ -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 */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_stack_build Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function builds a stack frame on the supplied thread's stack. */ +;/* The stack frame results in a fake interrupt return to the supplied */ +;/* function pointer. */ +;/* */ +;/* INPUT */ +;/* */ +;/* thread_ptr Pointer to thread control blk */ +;/* function_ptr Pointer to return function */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* _tx_thread_create Create thread service */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;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-M4 should look like the following after it is built: +; +; Stack Top: +; LR Interrupted LR (LR at time of PENDSV) +; r4 Initial value for r4 +; r5 Initial value for r5 +; r6 Initial value for r6 +; r7 Initial value for r7 +; r8 Initial value for r8 +; r9 Initial value for r9 +; r10 Initial value for r10 +; r11 Initial value for r11 +; r0 Initial value for r0 (Hardware stack starts here!!) +; r1 Initial value for r1 +; r2 Initial value for r2 +; r3 Initial value for r3 +; r12 Initial value for r12 +; lr Initial value for lr +; pc Initial value for pc +; xPSR Initial value for xPSR +; +; Stack Bottom: (higher memory address) */ +; + LDR r2, [r0, #16] ; Pickup end of stack area + BIC r2, r2, #0x7 ; Align frame for 8-byte alignment + SUB r2, r2, #68 ; Subtract frame size + LDR r3, =0xFFFFFFFD ; Build initial LR value + STR r3, [r2, #0] ; Save on the stack +; +; /* Actually build the stack frame. */ +; + MOV r3, #0 ; Build initial register value + STR r3, [r2, #4] ; Store initial r4 + STR r3, [r2, #8] ; Store initial r5 + STR r3, [r2, #12] ; Store initial r6 + STR r3, [r2, #16] ; Store initial r7 + STR r3, [r2, #20] ; Store initial r8 + STR r3, [r2, #24] ; Store initial r9 + STR r3, [r2, #28] ; Store initial r10 + STR r3, [r2, #32] ; Store initial r11 +; +; /* Hardware stack follows. */ +; + STR r3, [r2, #36] ; Store initial r0 + STR r3, [r2, #40] ; Store initial r1 + STR r3, [r2, #44] ; Store initial r2 + STR r3, [r2, #48] ; Store initial r3 + STR r3, [r2, #52] ; Store initial r12 + MOV r3, #0xFFFFFFFF ; Poison EXC_RETURN value + STR r3, [r2, #56] ; Store initial lr + STR r1, [r2, #60] ; Store initial pc + MOV r3, #0x01000000 ; Only T-bit need be set + STR r3, [r2, #64] ; Store initial xPSR +; +; /* Setup stack pointer. */ +; thread_ptr -> tx_thread_stack_ptr = r2; +; + STR r2, [r0, #8] ; Save stack pointer in thread's + ; control block + BX lr ; Return to caller +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_system_return.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_system_return.s new file mode 100644 index 00000000..9c453e61 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_thread_system_return.s @@ -0,0 +1,85 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Thread */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + AREA ||.text||, CODE, READONLY +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_thread_system_return Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function is target processor specific. It is used to transfer */ +;/* control from a thread back to the ThreadX system. Only a */ +;/* minimal context is saved since the compiler assumes temp registers */ +;/* are going to get slicked by a function call anyway. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_thread_schedule Thread scheduling loop */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* ThreadX components */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;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 + 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 +;} + END diff --git a/3rd_party/threadx/ports/cortex_m4/keil/src/tx_timer_interrupt.s b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_timer_interrupt.s new file mode 100644 index 00000000..f5160174 --- /dev/null +++ b/3rd_party/threadx/ports/cortex_m4/keil/src/tx_timer_interrupt.s @@ -0,0 +1,259 @@ +;/**************************************************************************/ +;/* */ +;/* Copyright (c) Microsoft Corporation. All rights reserved. */ +;/* */ +;/* This software is licensed under the Microsoft Software License */ +;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +;/* and in the root directory of this software. */ +;/* */ +;/**************************************************************************/ +; +; +;/**************************************************************************/ +;/**************************************************************************/ +;/** */ +;/** ThreadX Component */ +;/** */ +;/** Timer */ +;/** */ +;/**************************************************************************/ +;/**************************************************************************/ +; +; + IMPORT _tx_timer_time_slice + IMPORT _tx_timer_system_clock + IMPORT _tx_timer_current_ptr + IMPORT _tx_timer_list_start + IMPORT _tx_timer_list_end + IMPORT _tx_timer_expired_time_slice + IMPORT _tx_timer_expired + IMPORT _tx_thread_time_slice + IMPORT _tx_timer_expiration_process + IMPORT _tx_thread_preempt_disable + IMPORT _tx_thread_current_ptr + IMPORT _tx_thread_execute_ptr +; +; + AREA ||.text||, CODE, READONLY + PRESERVE8 +;/**************************************************************************/ +;/* */ +;/* FUNCTION RELEASE */ +;/* */ +;/* _tx_timer_interrupt Cortex-M4/AC5 */ +;/* 6.1 */ +;/* AUTHOR */ +;/* */ +;/* William E. Lamie, Microsoft Corporation */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function processes the hardware timer interrupt. This */ +;/* processing includes incrementing the system clock and checking for */ +;/* time slice and/or timer expiration. If either is found, the */ +;/* interrupt context save/restore functions are called along with the */ +;/* expiration functions. */ +;/* */ +;/* INPUT */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUT */ +;/* */ +;/* None */ +;/* */ +;/* CALLS */ +;/* */ +;/* _tx_timer_expiration_process Timer expiration processing */ +;/* _tx_thread_time_slice Time slice interrupted thread */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* interrupt vector */ +;/* */ +;/* RELEASE HISTORY */ +;/* */ +;/* DATE NAME DESCRIPTION */ +;/* */ +;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ +;/* */ +;/**************************************************************************/ +;VOID _tx_timer_interrupt(VOID) +;{ + EXPORT _tx_timer_interrupt +_tx_timer_interrupt +; +; /* Upon entry to this routine, it is assumed that context save has already +; been called, and therefore the compiler scratch registers are available +; for use. */ +; +; /* Increment the system clock. */ +; _tx_timer_system_clock++; +; + MOV32 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) +; { +; + MOV32 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? +; +; /* Set the time-slice expired flag. */ +; _tx_timer_expired_time_slice = TX_TRUE; +; + MOV32 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) +; { +; + MOV32 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; +; + MOV32 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) +; + MOV32 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; +; + MOV32 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)) +; { +; + MOV32 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 + MOV32 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) +; { +; + MOV32 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) +; { +; + MOV32 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 + MOV32 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 + MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address + LDR r1, [r0] ; Pickup the current thread pointer + MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address + LDR r3, [r2] ; Pickup the execute thread pointer + MOV32 r0, 0xE000ED04 ; Build address of control register + MOV32 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 +; +; } +; +__tx_timer_nothing_expired + + DSB ; Complete all memory access + BX lr ; Return to caller +; +;} + ALIGN + LTORG + END diff --git a/3rd_party/threadx/stm32f4xx_iar/readme_threadx.txt b/3rd_party/threadx/stm32f4xx_iar/readme_threadx.txt deleted file mode 100644 index 8d7e6605..00000000 --- a/3rd_party/threadx/stm32f4xx_iar/readme_threadx.txt +++ /dev/null @@ -1,248 +0,0 @@ - Express Logic's ThreadX for ST's STM32F4 Discovery Evaluation Board (Cortex-M4) - - Using the IAR Tools - - - *** DEMO VERSION *** - - -0. About This Version - -This version of ThreadX is for demonstration purposes only and may not -be used for any product development, either directly or indirectly. In -addition, this demonstration may not be used for any competitive purpose. - - -1. Installation - -ThreadX for ST's STM32F4 Discovery (Cortex-M4) is pre-installed in the evaluation -package. - - -2. Building the ThreadX run-time Library - -This demonstration version contains a pre-built ThreadX library, tx.a. The library is -intended for demonstration purposes only and thus has the following limitations: - - 10 Threads - 10 Timers - 10 Event Flag Groups - 10 Mutexes - 10 Queues - 10 Semaphores - 10 Block Pool - 10 Byte Pool - - -3. Demonstration System - -The ThreadX demonstration is designed to execute on the STM32F4 Discovery evaluation -board under the IAR Windows-based debugger. - -Building the demonstration is easy; simply make the demo_threadx.ewp project -the "active project" in the IAR Embedded Workbench and select the "Make" button. - -You should observe the compilation of demo_threadx.c (which is the demonstration -application) and linking with tx.a. The resulting file demo_threadx.out is a binary -file that can be downloaded and executed on the STM32F4 Discovery evaluation board using -the IAR debugger. - - -4. System Initialization - -The entry point in ThreadX for the (Cortex-M4) using IAR tools is at label -Reset_Handler. This is defined within the STM32 startup code, namely -the file startup_stm32f429xx.s. From this entry point, the IAR startup code -at __iar_program_start is called. This is where all static and global preset -C variable initialization processing takes place. - -The ThreadX tx_initialize_low_level.s file is responsible for setting up -various system data structures, and a periodic timer interrupt source. - -The _tx_initialize_low_level function inside of tx_initialize_low_level.s -also determines the first available address for use by the application, which -is supplied as the sole input parameter to your application definition function, -tx_application_define. To accomplish this, a section is created in -tx_initialize_low_level.s called FREE_MEM, which must be located after all -other RAM sections in memory. - - -5. Register Usage and Stack Frames - -The following defines the saved context stack frames for context switches -that occur as a result of interrupt handling or from thread-level API calls. -All suspended threads have the same stack frame in the Cortex-M4 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 - 0x08 r5 - 0x0C r6 - 0x10 r7 - 0x14 r8 - 0x18 r9 - 0x1C r10 (sl) - 0x20 r11 - 0x24 r0 (Hardware stack starts here!!) - 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 s0 - 0x08 s1 - 0x0C s2 - 0x10 s3 - 0x14 s4 - 0x18 s5 - 0x1C s6 - 0x20 s7 - 0x24 s8 - 0x28 s9 - 0x2C s10 - 0x30 s11 - 0x34 s12 - 0x38 s13 - 0x3C s14 - 0x40 s15 - 0x44 s16 - 0x48 s17 - 0x4C s18 - 0x50 s19 - 0x54 s20 - 0x58 s21 - 0x5C s22 - 0x60 s23 - 0x64 s24 - 0x68 s25 - 0x6C s26 - 0x70 s27 - 0x74 s28 - 0x78 s29 - 0x7C s30 - 0x80 s31 - 0x84 fpscr - 0x88 r4 - 0x8C r5 - 0x90 r6 - 0x94 r7 - 0x98 r8 - 0x9C r9 - 0xA0 r10 (sl) - 0xA4 r11 - 0xA8 r0 (Hardware stack starts here!!) - 0xAC r1 - 0xB0 r2 - 0xB4 r3 - 0xB8 r12 - 0xBC lr - 0xC0 pc - 0xC4 xPSR - -6. 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. - - -7. Interrupt Handling - -The Cortex-M4 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. - - -7.2 Managed Interrupts - -From version 5.6 going forward, 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 {lr} - - ; ISR processing goes here, including any needed function calls. - - POP {lr} - BX lr - -Backward compatibility to the previous style assembly ISRs is maintained, which was of -the form: - - PUBLIC __legacy_isr_handler -__legacy_isr_handler: - PUSH {lr} - BL _tx_thread_context_save - -; /* Do interrupt handler work here */ -; /* .... */ - - B _tx_thread_context_restore - - -8. 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. - - -9. VFP Support - -When applicable, ThreadX for the STM32F4 Discovery (Cortex-M4) supports 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 -is required. - - -10. Revision History - -08/01/2017 Initial ThreadX version for STM32F4 Discovery (Cortex-M4) using IAR's ARM tools. - - -Copyright(c) 1996-2017 Express Logic, Inc. - - -Express Logic, Inc. -11323 West Bernardo Court -San Diego, CA 92127 - -www.expresslogic.com - diff --git a/3rd_party/threadx/tm4c123xx_iar/readme_threadx.txt b/3rd_party/threadx/tm4c123xx_iar/readme_threadx.txt deleted file mode 100644 index ff8f3434..00000000 --- a/3rd_party/threadx/tm4c123xx_iar/readme_threadx.txt +++ /dev/null @@ -1,247 +0,0 @@ - Express Logic's ThreadX for EK-TM4C123GXL Evaluation Board (Cortex-M4) - - Using the IAR Tools - - - *** DEMO VERSION *** - - -0. About This Version - -This version of ThreadX is for demonstration purposes only and may not -be used for any product development, either directly or indirectly. In -addition, this demonstration may not be used for any competitive purpose. - - -1. Installation - -ThreadX for EK-TM4C123GXL (Cortex-M4) is pre-installed in the evaluation package. - - -2. Building the ThreadX run-time Library - -This demonstration version contains a pre-built ThreadX library, tx.a. The library is -intended for demonstration purposes only and thus has the following limitations: - - 10 Threads - 10 Timers - 10 Event Flag Groups - 10 Mutexes - 10 Queues - 10 Semaphores - 10 Block Pool - 10 Byte Pool - - -3. Demonstration System - -The ThreadX demonstration is designed to execute on the EK-TM4C123GXL evaluation -board under the IAR Windows-based debugger. - -Building the demonstration is easy; simply make the demo_threadx.ewp project -the "active project" in the IAR Embedded Workbench and select the "Make" button. - -You should observe the compilation of demo_threadx.c (which is the demonstration -application) and linking with tx.a. The resulting file demo_threadx.out is a binary -file that can be downloaded and executed on the EK-TM4C123GXL evaluation board using -the IAR debugger. - - -4. System Initialization - -The entry point in ThreadX for the (Cortex-M4) using IAR tools is at label -__Reset_Handler. This is defined within the EK-TM4C123GXL startup code, namely -the file startup_ewarm.s. From this entry point, the IAR startup code -at __iar_program_start is called. This is where all static and global preset -C variable initialization processing takes place. - -The ThreadX tx_initialize_low_level.s file is responsible for setting up -various system data structures, and a periodic timer interrupt source. - -The _tx_initialize_low_level function inside of tx_initialize_low_level.s -also determines the first available address for use by the application, which -is supplied as the sole input parameter to your application definition function, -tx_application_define. To accomplish this, a section is created in -tx_initialize_low_level.s called FREE_MEM, which must be located after all -other RAM sections in memory. - - -5. Register Usage and Stack Frames - -The following defines the saved context stack frames for context switches -that occur as a result of interrupt handling or from thread-level API calls. -All suspended threads have the same stack frame in the Cortex-M4 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 - 0x08 r5 - 0x0C r6 - 0x10 r7 - 0x14 r8 - 0x18 r9 - 0x1C r10 (sl) - 0x20 r11 - 0x24 r0 (Hardware stack starts here!!) - 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 s0 - 0x08 s1 - 0x0C s2 - 0x10 s3 - 0x14 s4 - 0x18 s5 - 0x1C s6 - 0x20 s7 - 0x24 s8 - 0x28 s9 - 0x2C s10 - 0x30 s11 - 0x34 s12 - 0x38 s13 - 0x3C s14 - 0x40 s15 - 0x44 s16 - 0x48 s17 - 0x4C s18 - 0x50 s19 - 0x54 s20 - 0x58 s21 - 0x5C s22 - 0x60 s23 - 0x64 s24 - 0x68 s25 - 0x6C s26 - 0x70 s27 - 0x74 s28 - 0x78 s29 - 0x7C s30 - 0x80 s31 - 0x84 fpscr - 0x88 r4 - 0x8C r5 - 0x90 r6 - 0x94 r7 - 0x98 r8 - 0x9C r9 - 0xA0 r10 (sl) - 0xA4 r11 - 0xA8 r0 (Hardware stack starts here!!) - 0xAC r1 - 0xB0 r2 - 0xB4 r3 - 0xB8 r12 - 0xBC lr - 0xC0 pc - 0xC4 xPSR - -6. 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. - - -7. Interrupt Handling - -The Cortex-M4 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. - - -7.2 Managed Interrupts - -From version 5.6 going forward, 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 {lr} - - ; ISR processing goes here, including any needed function calls. - - POP {lr} - BX lr - -Backward compatibility to the previous style assembly ISRs is maintained, which was of -the form: - - PUBLIC __legacy_isr_handler -__legacy_isr_handler: - PUSH {lr} - BL _tx_thread_context_save - -; /* Do interrupt handler work here */ -; /* .... */ - - B _tx_thread_context_restore - - -8. 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. - - -9. VFP Support - -When applicable, ThreadX for the EK-TM4C123GXL (Cortex-M4) supports 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 -is required. - - -10. Revision History - -08/01/2017 Initial ThreadX version for EK-TM4C123GXL (Cortex-M4) using IAR's ARM tools. - - -Copyright(c) 1996-2017 Express Logic, Inc. - - -Express Logic, Inc. -11323 West Bernardo Court -San Diego, CA 92127 - -www.expresslogic.com - diff --git a/3rd_party/threadx/tm4c123xx_iar/tx_port.h b/3rd_party/threadx/tm4c123xx_iar/tx_port.h deleted file mode 100644 index f8605352..00000000 --- a/3rd_party/threadx/tm4c123xx_iar/tx_port.h +++ /dev/null @@ -1,429 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 1996-2017 by Express Logic Inc. */ -/* */ -/* This software is copyrighted by and is the sole property of Express */ -/* Logic, Inc. All rights, title, ownership, or other interests */ -/* in the software remain the property of Express Logic, Inc. This */ -/* software may only be used in accordance with the corresponding */ -/* license agreement. Any unauthorized use, duplication, transmission, */ -/* distribution, or disclosure of this software is expressly forbidden. */ -/* */ -/* This Copyright notice may not be removed or modified without prior */ -/* written consent of Express Logic, Inc. */ -/* */ -/* Express Logic, Inc. reserves the right to modify this software */ -/* without notice. */ -/* */ -/* Express Logic, Inc. info@expresslogic.com */ -/* 11423 West Bernardo Court http://www.expresslogic.com */ -/* San Diego, CA 92127 */ -/* */ -/**************************************************************************/ - - -/**************************************************************************/ -/**************************************************************************/ -/** */ -/** ThreadX Component */ -/** */ -/** Port Specific */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - -/**************************************************************************/ -/* */ -/* PORT SPECIFIC C INFORMATION RELEASE */ -/* */ -/* tx_port.h Cortex-M4/IAR */ -/* 5.6 */ -/* */ -/* AUTHOR */ -/* */ -/* William E. Lamie, Express Logic, Inc. */ -/* */ -/* DESCRIPTION */ -/* */ -/* This file contains data type definitions that make the ThreadX */ -/* real-time kernel function identically on a variety of different */ -/* processor architectures. For example, the size or number of bits */ -/* in an "int" data type vary between microprocessor architectures and */ -/* even C compilers for the same microprocessor. ThreadX does not */ -/* directly use native C data types. Instead, ThreadX creates its */ -/* own special types that can be mapped to actual data types by this */ -/* file to guarantee consistency in the interface and functionality. */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 10-10-2010 William E. Lamie Initial Cortex-M4 IAR */ -/* Support Version 5.0 */ -/* 07-15-2011 William E. Lamie Modified comment(s), added */ -/* IAR thread-safe library */ -/* support, and updated */ -/* version string, resulting */ -/* in version 5.1 */ -/* 04-15-2012 William E. Lamie Modified comment(s), added */ -/* FPU enable/disable function */ -/* prototypes, and updated */ -/* version string, resulting */ -/* in version 5.2 */ -/* 01-01-2014 William E. Lamie Modified comment(s), added */ -/* FPU enable/disable struct */ -/* member, and updated */ -/* version string, resulting */ -/* in version 5.3 */ -/* 04-15-2014 William E. Lamie Modified comment(s), and */ -/* updated version string, */ -/* resulting in version 5.4 */ -/* 09-01-2014 William E. Lamie Modified comment(s), and */ -/* updated version string, */ -/* resulting in version 5.5 */ -/* 06-01-2017 William E. Lamie Modified comment(s), added */ -/* support for new thread-safe */ -/* IAR libraries, removed */ -/* unneeded VFP enable flag, */ -/* added logic to remove the */ -/* need for context */ -/* save/restore calls in ISRs, */ -/* modified code for MISRA */ -/* compliance, and updated */ -/* version string, resulting */ -/* in version 5.6 */ -/* */ -/**************************************************************************/ - -#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 -#include -#include -#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT -#include -#endif - - -/* Define ThreadX basic types for this port. */ - -#define VOID void -typedef char CHAR; -typedef unsigned char UCHAR; -typedef int INT; -typedef unsigned int UINT; -typedef long LONG; -typedef unsigned long ULONG; -typedef short SHORT; -typedef unsigned short USHORT; - - -/* Define the priority levels for ThreadX. Legal values range - from 32 to 1024 and MUST be evenly divisible by 32. */ - -#ifndef TX_MAX_PRIORITIES -#define TX_MAX_PRIORITIES 32 -#endif - - -/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during - thread creation is less than this value, the thread create call will return an error. */ - -#ifndef TX_MINIMUM_STACK -#define TX_MINIMUM_STACK 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-M3 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 - - -/* 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; -#else -#define TX_THREAD_EXTENSION_2 -#endif -#ifndef TX_ENABLE_EXECUTION_CHANGE_NOTIFY -#define TX_THREAD_EXTENSION_3 -#else -#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \ - unsigned long long tx_thread_execution_time_last_start; -#endif - - -/* Define the port extensions of the remaining ThreadX objects. */ - -#define TX_BLOCK_POOL_EXTENSION -#define TX_BYTE_POOL_EXTENSION -#define TX_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 -#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 -#ifndef TX_MISRA_ENABLE -#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR()) -#else -ULONG _tx_misra_ipsr_get(VOID); -#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) -#endif -#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++; - - -/* Determine if the ARM architecture has the CLZ instruction. This is available on - architectures v5 and above. If available, redefine the macro for calculating the - lowest bit set. */ - -#ifndef TX_DISABLE_INLINE - -#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \ - b = (UINT) __CLZ(m); \ - b = 31 - b; -#endif - - -/* Define ThreadX interrupt lockout and restore macros for protection on - access of critical kernel information. The restore interrupt macro must - restore the interrupt posture of the running thread prior to the value - present prior to the disable macro. In most cases, the save area macro - is used to define a local function save area for the disable and restore - macros. */ - -#ifdef TX_DISABLE_INLINE - -UINT _tx_thread_interrupt_disable(VOID); -VOID _tx_thread_interrupt_restore(UINT previous_posture); - -#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; - -#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); - -#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); - -#else - -#define TX_INTERRUPT_SAVE_AREA __istate_t interrupt_save; -#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();}; -#define TX_RESTORE {__set_interrupt_state(interrupt_save);}; - -#define _tx_thread_system_return _tx_thread_system_return_inline - -static void _tx_thread_system_return_inline(void) -{ -__istate_t interrupt_save; - - /* Set PendSV to invoke ThreadX scheduler. */ - *((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - if (__get_IPSR() == 0) - { - interrupt_save = __get_interrupt_state(); - __enable_interrupt(); - __set_interrupt_state(interrupt_save); - } -} - -#endif - - -/* Define FPU extension for the Cortex-M4. 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 interrupt lockout macros for each ThreadX object. */ - -#define TX_BLOCK_POOL_DISABLE TX_DISABLE -#define TX_BYTE_POOL_DISABLE TX_DISABLE -#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE -#define TX_MUTEX_DISABLE TX_DISABLE -#define TX_QUEUE_DISABLE TX_DISABLE -#define TX_SEMAPHORE_DISABLE TX_DISABLE - - -/* Define the version ID of ThreadX. This may be utilized by the application. */ - -#ifdef TX_THREAD_INIT -CHAR _tx_version_id[] = - "Copyright (c) 1996-2017 Express Logic Inc. * ThreadX Cortex-M4/IAR Version G5.8.5.6 SN: X-WARE_PLATFORM_EK-TM4C123GXL_LaunchPad_Evaluation_Version_08-01-2017 *"; -#else -#ifdef TX_MISRA_ENABLE -extern CHAR _tx_version_id[100]; -#else -extern CHAR _tx_version_id[]; -#endif -#endif - - -#endif - - - diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile index 8a24e562..d18b08c0 100644 --- a/doxygen/Doxyfile +++ b/doxygen/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "QP/C" -PROJECT_NUMBER = "6.9.2" +PROJECT_NUMBER = "6.9.3" PROJECT_BRIEF = PROJECT_LOGO = images/header_logo_ql.png OUTPUT_DIRECTORY = diff --git a/doxygen/Doxyfile-CHM b/doxygen/Doxyfile-CHM index 35cdd9db..626d6ec3 100644 --- a/doxygen/Doxyfile-CHM +++ b/doxygen/Doxyfile-CHM @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "QP/C" -PROJECT_NUMBER = "6.9.2" +PROJECT_NUMBER = "6.9.3" PROJECT_BRIEF = PROJECT_LOGO = images/header_logo_ql.png OUTPUT_DIRECTORY = diff --git a/doxygen/Doxyfile-DOC b/doxygen/Doxyfile-DOC index b5200768..772e257c 100644 --- a/doxygen/Doxyfile-DOC +++ b/doxygen/Doxyfile-DOC @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "QP/C" -PROJECT_NUMBER = "6.9.2" +PROJECT_NUMBER = "6.9.3" PROJECT_BRIEF = PROJECT_LOGO = images/header_logo_ql.png OUTPUT_DIRECTORY = diff --git a/doxygen/exa.dox b/doxygen/exa.dox index f890b674..f9a3bcb2 100644 --- a/doxygen/exa.dox +++ b/doxygen/exa.dox @@ -304,9 +304,9 @@ To work with QP/C effectively, you need to learn a bit more about active objects 1. The book “Practical UML Statecharts in C/C++, 2nd Edition” [PSiCC2] and the companion web-page to the book (https://www.state-machine.com/psicc2/ 2. Free Support Forum for QP/QM (https://sourceforge.net/p/qpc/discussion/668726 ) -3. QP Code Downloads summary (https://www.state-machine.com/downloads ) -4. QP Application Notes (https://www.state-machine.com/doc/an ) -5. "State Space" Blog (https://embeddedgurus.com/state-space/ ) +3. QP Code Downloads summary (https://www.state-machine.com/#Downloads ) +4. QP Application Notes (https://www.state-machine.com/an/ ) +5. "State Space" Blog (https://www.state-machine.com/category/blog/ ) @next{exa_ref} */ diff --git a/doxygen/history.dox b/doxygen/history.dox index fb4a1397..d9823142 100644 --- a/doxygen/history.dox +++ b/doxygen/history.dox @@ -1,6 +1,58 @@ /** @page history Revision History +@section qpc_6_9_3 Version 6.9.3, 2021-04-12 + +__Feature Requests:__ +- [feature#191 "Add QS local filtering to QF_PUBLISH()"](https://sourceforge.net/p/qpc/feature-requests/191/) + +The feature has been implemented by means of the "sender" parameter of the `QF_PUBLISH()` macro, which must now be a pointer to a struct that has the `prio` member. This design enables applying QS local filter to the `prio` as the QS-Id. This works for publishing events from active objects. For publishing events outside active objects (e.g., from ISRs), the header file `qs.h` provides a type `QSpyId`, which should be used to define QS ID variables to be used as "sender" in `QF_PUBLISH()`. + +@note +This change only affects the Spy build configuration, where the QS software tracing instrumentation is enabled. The existing code could require modifications to provide "sender" pointer that can access `prio` directly. For example, AOs would need to call `QF_PUBLISH(e, &me->super)` instead of `QF_PUBLISH(e, me)`. + + +- [feature#185 "Add possibility of assigning name to AO threads in QP-RTOS ports"](https://sourceforge.net/p/qpc/feature-requests/185/) + +This feature request is now implemented uniformely in all QP-ports to 3rd-party RTOSes by means of the generic QP API QActive_setAttr(). Specifically, the QP port will allow you to set the thread name by calling QActive_setAttr() before calling QACTIVE_START(). + + +__Bug Fixes:__ +- [bug#292 "QP-C-C++ on 64 Bit Linux - Setting of Current-Obj - AO_Obj from QView raises segmentation fault"](https://sourceforge.net/p/qpc/bugs/292/) +- [bug#293 "[Qpccp 6.9.2] test of assertion fail now"](https://sourceforge.net/p/qpc/bugs/293/) +- [bug#298 "ARM Cortex-M Erratum 838869 Handled Inconsistently in Ports"](https://sourceforge.net/p/qpc/bugs/298/) + + +__Source code changes:__ +- `qpc/include/qf.h` - feature#191 +- `qpc/include/qs.h` - feature#191 +- `qpc/src/qf/qf_ps.c` - feature#191 +- `qpc/src/qs/qs_rx.c` - feature#191 and bug#292 + + +__Modified QP/C ports:__ +- `qpc/ports/arm-cm/` - fixed [bug#298](https://sourceforge.net/p/qpc/bugs/298/) +- `qpc/ports/embos/` - implemented [feature#185](https://sourceforge.net/p/qpc/feature-requests/185/) +- `qpc/ports/threadx/` - implemented [feature#185](https://sourceforge.net/p/qpc/feature-requests/185/) +- `qpc/ports/ucos2/` - implemented [feature#185](https://sourceforge.net/p/qpc/feature-requests/185/) +- `qpc/ports/win32/` - added QSpy64 (64-bit) build configuration to the Visual Studio project +- `qpc/ports/win32-qv/` - added QSpy64 (64-bit) build configuration to the Visual Studio project +- `qpc/ports/win32-quit/` - added "port" used for "QP Unit Internal Testing" (QUIT) + + +__Updated examples:__ +- all examples using `QF_PUBLISH()` - adjusted the `sender` parameter of the macro to have the `prio` member +- `qpc/examples/arm-cm/` - fixed [bug#298](https://sourceforge.net/p/qpc/bugs/298/) (added calls to `QV|QK|QXK_ARM_ERRATUM_838869()`) +- `qpc/examples/qutest/self_test/test/` - added examples of the Python include files (`*.pyi`) for the new [include command](https://www.state-machine.com/qtools/namespacequtest__dsl.html). +- `qpc/examples/arm-cm/dpp_efm32-slstk3401a/win32-gui/` - corrected handling of user-drawn buttons in `bsp.c` +- `qpc/examples/arm-cm/game_efm32-slstk3401a/win32-gui/` - corrected handling of user-drawn buttons in `bsp.c` + + +__Updated 3rd-Party Components:__ +- `qpc/3rd_party/threadx` to version 6.1.6 (latest open source version from [GitHub](https://github.com/azure-rtos/threadx) ) + + + @section qpc_6_9_2 Version 6.9.2, 2021-01-18 The main purpose of this release is a redesign of the QS-RX (software tracing input) to implement the feature request #187: @@ -40,7 +92,7 @@ __Modified QP/C ports:__ __Added QP/C ports:__ -- `qpc/ports/freertos-esp32/` - added new port to FreeRTOS-ESP32 +- `qpc/ports/freertos-esp32/` - added new *experimental* port to FreeRTOS-ESP32 __Updated examples:__ @@ -1024,7 +1076,7 @@ Changes in detail: This release adds support for the new board: EFM32-SLSTK3401A (Pearl Gecko Starter Kit from Silicon Labs). This board replaces the Stellaris EK-LM3S811 board, which has been discontinued. (The Stellaris EK-LM3S811 board had been used in the "Fly 'n' Shoot" game example accompanying the PSiCC2 book). This release also introduces a new version of the QWIN GUI Toolkit in the Windows prototypes for the "Fly 'n' Shoot" game and the DPP-GUI -version (see https://www.state-machine.com/products/#QWIN). +version (see https://www.state-machine.com/products/qtools/#QWin). Additionally, this release also includes the QP/C integration with the emWin emgedded GUI from SEGGER, which is also the same product as uC/GUI distributed by Micrium (@ref exa_emwin). diff --git a/doxygen/main.dox b/doxygen/main.dox index 7da95150..7496c4db 100644 --- a/doxygen/main.dox +++ b/doxygen/main.dox @@ -8,12 +8,12 @@ To check what's new in QP/C, please see @ref history "QP/C Revision History". @section ab_about What is it? -QP/C™ (Quantum Platform in C) is a lightweight Real-Time Embedded Framework (RTEF) for building modern, responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C™ RTEF is a member of a larger family of real-time embedded frameworks (RTEFs) consisting of QP/C and QP/C++ frameworks, which are all strictly quality controlled, thoroughly documented, and available under @ref licensing "dual licensing model". +QP/C™ (Quantum Platform in C) is a lightweight Real-Time Embedded Framework (RTEF) for building modern, responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C™ RTEF is a member of a larger family of real-time embedded frameworks (RTEFs) consisting of QP/C and QP/C++ frameworks, which are all strictly quality controlled, thoroughly documented, and available under @ref licensing "dual licensing model". -The behavior of active objects is specified in QP/C by means of hierarchical state machines (UML statecharts). The framework supports @ref sm "manual coding of UML state machines in C" as well as automatic code generation by means of the free QM™ model-based design tool. +The behavior of active objects is specified in QP/C by means of hierarchical state machines (UML statecharts). The framework supports @ref sm "manual coding of UML state machines in C" as well as automatic code generation by means of the free QM™ model-based design tool. @attention -To use QP/C™ effectively, you need to understand the key concepts that underline the architecture of the framework and your applications based on the framework. +To use QP/C™ effectively, you need to understand the key concepts that underline the architecture of the framework and your applications based on the framework.
@@ -25,8 +25,8 @@ To use QP/C™ effectively, you need to understand the active objects (actors), which is inherently **safer**, more extensible, and easier to understand than the usual _shared-state concurrency_ based on a traditional Real-Time Operating System (RTOS). -- to provide a simple-to-use coding techniques for hierarchical state machines, with which to implement the behavior of active objects. +- to provide a reusable event-driven **architecture** based on active objects (actors), which is inherently **safer**, more extensible, and easier to understand than the usual _shared-state concurrency_ based on a traditional Real-Time Operating System (RTOS). +- to provide a simple-to-use coding techniques for hierarchical state machines, with which to implement the behavior of active objects. - to provide efficient and thread-safe asynchronous mechanisms for active objects to communicate, such as direct event passing and publish-subscribe. - to provide event-driven timing services (time events). - to provide a selection of built-in real-time kernels to run the QP applications, such as the cooperative @ref qv "QV kernel", the preemptive non-blocking @ref qk "QK kernel", and the preemptive blocking @ref qxk "QXK kernel". @@ -38,7 +38,7 @@ The main goals of the QP/C™ framework are: @section ab_special What's special about it? -The QP/C™ Real-Time Embedded Framework (RTEF) is a unique offering on the embedded software market. It provides a modern, reusable **architecture** of embedded applications, which combines object-orientation with the particular model of concurrency, known as active objects (actors). This architecture is generally **safer**, more responsive and easier to understand than "free threading" with a traditional Real-Time Operating System (RTOS). It also provides sufficiently high level of abstraction and the right abstractions to effectively apply modeling and code generation to deeply embedded systems. +The QP/C™ Real-Time Embedded Framework (RTEF) is a unique offering on the embedded software market. It provides a modern, reusable **architecture** of embedded applications, which combines object-orientation with the particular model of concurrency, known as active objects (actors). This architecture is generally **safer**, more responsive and easier to understand than "free threading" with a traditional Real-Time Operating System (RTOS). It also provides sufficiently high level of abstraction and the right abstractions to effectively apply modeling and code generation to deeply embedded systems. @@ -66,10 +66,10 @@ The most unique characteristic of the QP/C™ framework is its very small fo @subsection hsms Hierarchical State Machines The behavior of active objects is specified in QP by means of -hierarchical state machines (UML statecharts). The framework supports @ref sm "manual coding of UML state machines in C" (or C++ in case of QP/C++) as well as fully **automatic code generation** by means of the free graphical QM™ model-based design (MBD) tool. +hierarchical state machines (UML statecharts). The framework supports @ref sm "manual coding of UML state machines in C" (or C++ in case of QP/C++) as well as fully **automatic code generation** by means of the free graphical QM™ model-based design (MBD) tool. @remarks -State machines can be an incredibly powerful technique, but they require an event-driven **infrastructure** (framework) that provides, at a minimum: a run-to-completion (RTC) execution context for each state machine, queuing of events, and event-based timing services. This is really the pivotal point. Without an event-driven framewok (like QP/C), state machines are like cars without an infrastructure of roads. +State machines can be an incredibly powerful technique, but they require an event-driven **infrastructure** (framework) that provides, at a minimum: a run-to-completion (RTC) execution context for each state machine, queuing of events, and event-based timing services. This is really the pivotal point. Without an event-driven framewok (like QP/C), state machines are like cars without an infrastructure of roads. @subsection kernels Built-in Kernels diff --git a/doxygen/snippets/qf_state.c b/doxygen/snippets/qf_state.c index 564f51fe..44bc4e38 100644 --- a/doxygen/snippets/qf_state.c +++ b/doxygen/snippets/qf_state.c @@ -11,7 +11,7 @@ QState Philo_eating(Philo * const me, QEvt const * const e) { QTimeEvt_disarm(&me->timeEvt); pe = Q_NEW(TableEvt, DONE_SIG); pe->philNum = me->num; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); status = Q_HANDLED(); break; } diff --git a/doxygen/struct.dox b/doxygen/struct.dox index 4f3a482b..c12425d3 100644 --- a/doxygen/struct.dox +++ b/doxygen/struct.dox @@ -29,7 +29,7 @@ The standard QP/C distribution contains many @ref exa "Example Projects", which @section comp Components of QP/C -

As shown in the diagram below, the QP/C framework has a layered structure. The Target hardware sits at the bottom. The Board Support Package (BSP) above it provides access to the board-specific features, such as the peripherals. The real-time kernel (@ref comp_qv "QV", @ref comp_qk "QK", @ref comp_qxk "QXK", or a conventional @ref ports_rtos "3rd-party RTOS") provides the foundation for multitasking, such as task scheduling, context-switching, and inter-task communication. Based on these services, the active object framework (@ref comp_qf "QF") supplies the event-driven infrastructure for executing active objects and ensuring thread-safe event-driven exchanges among them. Finally, the event-processor (@ref comp_qep "QEP") implements the [hierarchical state machine](https://www.state-machine.com/doc/concepts#HSM) semantics (based on UML statecharts). The top layer is the application-level code consisting of loosely-coupled [active objects](https://www.state-machine.com/doc/concepts#Active). +

As shown in the diagram below, the QP/C framework has a layered structure. The Target hardware sits at the bottom. The Board Support Package (BSP) above it provides access to the board-specific features, such as the peripherals. The real-time kernel (@ref comp_qv "QV", @ref comp_qk "QK", @ref comp_qxk "QXK", or a conventional @ref ports_rtos "3rd-party RTOS") provides the foundation for multitasking, such as task scheduling, context-switching, and inter-task communication. Based on these services, the active object framework (@ref comp_qf "QF") supplies the event-driven infrastructure for executing active objects and ensuring thread-safe event-driven exchanges among them. Finally, the event-processor (@ref comp_qep "QEP") implements the [hierarchical state machine](https://www.state-machine.com/fsm/#HSM) semantics (based on UML statecharts). The top layer is the application-level code consisting of loosely-coupled [active objects](https://www.state-machine.com/active-object/).

@image html qp_components.jpg "Components of the QP Framework" @@ -37,11 +37,11 @@ The standard QP/C distribution contains many @ref exa "Example Projects", which @subsection comp_qep QEP Hierarchical Event Processor -QEP is a universal "event processor" that provides implementation of hierarchical state machines (UML statecharts) in highly readable ISO-C. The hallmark of the QEP state machine implementation strategy is **traceability**, which means that every state machine element is mapped to code precisely, unambiguously, and exactly once. QEP fully supports hierarchical state nesting, which is the fundamental mechanism for reusing behavior across many states instead of repeating the same actions and transitions over and over again. (See @ref qep for detailed documentation). +QEP is a universal "event processor" that provides implementation of hierarchical state machines (UML statecharts) in highly readable ISO-C. The hallmark of the QEP state machine implementation strategy is **traceability**, which means that every state machine element is mapped to code precisely, unambiguously, and exactly once. QEP fully supports hierarchical state nesting, which is the fundamental mechanism for reusing behavior across many states instead of repeating the same actions and transitions over and over again. (See @ref qep for detailed documentation). @subsection comp_qf QF Active-Object Framework -QF is a lightweight, event-driven, active object framework specifically designed for real-time embedded (RTE) systems. The main job of the framework is to guarantee **thread-safe**, run-to-completion event processing within each active object. This includes direct event posting as well as publish-subscribe event delivery, event queuing, and time events (time-delayed requests for posing events). (See @ref qf for detailed documentation). +QF is a lightweight, event-driven, active object framework specifically designed for real-time embedded (RTE) systems. The main job of the framework is to guarantee **thread-safe**, run-to-completion event processing within each active object. This includes direct event posting as well as publish-subscribe event delivery, event queuing, and time events (time-delayed requests for posing events). (See @ref qf for detailed documentation). @subsection comp_qv QV Cooperative Kernel @@ -101,7 +101,7 @@ The figure below shows the main classes comprising the QP/C framework and their @section sm State Machines -The behavior of each active object in QP/C is specified by means of a hierarchical state machine (UML statechart), which is the most effective and elegant technique of describing event-driven behavior. The most important innovation of UML state machines over classical finite state machines (FSMs) is the hierarchical state nesting. The value of state nesting lies in avoiding repetitions, which are inevitable in the traditional "flat" FSM formalism and are the main reason for the "state-transition explosion" in FSMs. The semantics of state nesting allow substates to define only the differences of behavior from the superstates, thus promoting sharing and reusing behavior. +The behavior of each active object in QP/C is specified by means of a hierarchical state machine (UML statechart), which is the most effective and elegant technique of describing event-driven behavior. The most important innovation of UML state machines over classical finite state machines (FSMs) is the hierarchical state nesting. The value of state nesting lies in avoiding repetitions, which are inevitable in the traditional "flat" FSM formalism and are the main reason for the "state-transition explosion" in FSMs. The semantics of state nesting allow substates to define only the differences of behavior from the superstates, thus promoting sharing and reusing behavior. @note The Quantum Leaps Application Note A Crash Course in UML State Machines introduces the main state machine concepts backed up by examples. @@ -137,7 +137,7 @@ The QS software tracing instrumentation is only active in the **Spy build config Design by Contract (DbC) is a philosophy that views a software system as a set of components whose collaboration is based on precisely defined specifications of mutual obligations — the contracts. The central idea of this method is to inherently embed the contracts in the code and validate them automatically at runtime. In C and C++, the most important aspects of DbC (the contracts) can be implemented with assertions. Assertions are increasingly popular among the developers of mission-critical software. For example, NASA requires certain density of assertions in such software. -In the context of the QP/C framework, DbC provides an excellent methodology for implementing a very robust error-handling policy. Due to inversion of control so typical in all event-driven systems, the QP/C framework controls many more aspects of the application than a traditional RTOS. A framework is in a much better position to make sure that the application is performing correctly, rather than the application to check error codes or catch exceptions originating from the framework. +In the context of the QP/C framework, DbC provides an excellent methodology for implementing a very robust error-handling policy. Due to inversion of control so typical in all event-driven systems, the QP/C framework controls many more aspects of the application than a traditional RTOS. A framework is in a much better position to make sure that the application is performing correctly, rather than the application to check error codes or catch exceptions originating from the framework. @section coding Coding Standard diff --git a/examples/README.url b/examples/README.url index 1423b095..92ae834d 100644 --- a/examples/README.url +++ b/examples/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa.html +URL=https://www.state-machine.com/qpc/exa.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/README.url b/examples/arm-cm/README.url index 79533031..8f04e895 100644 --- a/examples/arm-cm/README.url +++ b/examples/arm-cm/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_arm-cm.html +URL=https://www.state-machine.com/qpc/exa_arm-cm.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/blinky_efm32-slstk3401a/README.url b/examples/arm-cm/blinky_efm32-slstk3401a/README.url index 1f03e516..7557877b 100644 --- a/examples/arm-cm/blinky_efm32-slstk3401a/README.url +++ b/examples/arm-cm/blinky_efm32-slstk3401a/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_blinky_ek-tm4c123gxl.html +URL=https://www.state-machine.com/qpc/arm-cm_blinky_ek-tm4c123gxl.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/blinky_ek-tm4c123gxl/README.url b/examples/arm-cm/blinky_ek-tm4c123gxl/README.url index 5f8f3b65..d3cc38ff 100644 --- a/examples/arm-cm/blinky_ek-tm4c123gxl/README.url +++ b/examples/arm-cm/blinky_ek-tm4c123gxl/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_blinky_efm32-slstk3401a.html +URL=https://www.state-machine.com/qpc/arm-cm_blinky_efm32-slstk3401a.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/README.url b/examples/arm-cm/dpp_efm32-slstk3401a/README.url index b51af616..4903934a 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/README.url +++ b/examples/arm-cm/dpp_efm32-slstk3401a/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_dpp_efm32-slstk3401a.html +URL=https://www.state-machine.com/qpc/arm-cm_dpp_efm32-slstk3401a.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/dpp.qm b/examples/arm-cm/dpp_efm32-slstk3401a/dpp.qm index 2ac9aa73..43ad83c4 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/dpp.qm +++ b/examples/arm-cm/dpp_efm32-slstk3401a/dpp.qm @@ -119,7 +119,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -212,7 +212,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -235,7 +235,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -277,7 +277,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -288,7 +288,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/philo.c b/examples/arm-cm/dpp_efm32-slstk3401a/philo.c index c9c9adfe..2210d649 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/philo.c +++ b/examples/arm-cm/dpp_efm32-slstk3401a/philo.c @@ -205,7 +205,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.c b/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.c index 77d0ec3c..7e7f6c58 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.c +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -64,9 +64,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL)); enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qv/bsp.c b/examples/arm-cm/dpp_efm32-slstk3401a/qv/bsp.c index 220a60a0..45d1573a 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qv/bsp.c +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, EFM32-SLSTK3401A board, cooperative QV kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -64,9 +64,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL)); enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.c b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.c index 322a711c..2003fd82 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.c +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -64,9 +64,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL)); enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.c b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.c index fb5d4093..7874322e 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.c +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.c @@ -88,7 +88,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/table.c b/examples/arm-cm/dpp_efm32-slstk3401a/table.c index 66747a1a..33f68997 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/table.c +++ b/examples/arm-cm/dpp_efm32-slstk3401a/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/README.url b/examples/arm-cm/dpp_ek-tm4c123gxl/README.url index 156cfa21..46de3d79 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/README.url +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_dpp_ek-tm4c123gxl.html +URL=https://www.state-machine.com/qpc/arm-cm_dpp_ek-tm4c123gxl.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/dpp.qm b/examples/arm-cm/dpp_ek-tm4c123gxl/dpp.qm index c6c7200c..43ad83c4 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/dpp.qm +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/dpp.qm @@ -119,7 +119,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -157,7 +157,6 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); uint8_t n; - (void)par; /* unused parameter */ QS_OBJ_DICTIONARY(&Table_inst); @@ -213,7 +212,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -236,7 +235,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -278,7 +277,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -289,7 +288,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/philo.c b/examples/arm-cm/dpp_ek-tm4c123gxl/philo.c index c9c9adfe..2210d649 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/philo.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/philo.c @@ -205,7 +205,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.c b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.c index 5a2c70cd..7f1cb108 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, EK-TM4C123GXL board, preemptive QK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -64,9 +64,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIOPortA_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIOPortA_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE (1U << 7) diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/gnu_with-stack-prot/bsp_stack-prot.c b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/gnu_with-stack-prot/bsp_stack-prot.c index 74e9c72c..352a6a50 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/gnu_with-stack-prot/bsp_stack-prot.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/gnu_with-stack-prot/bsp_stack-prot.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, EK-TM4C123GXL board, preemptive QK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -64,9 +64,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = (uint8_t)0; - static uint8_t const l_GPIOPortA_IRQHandler = (uint8_t)0; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIOPortA_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE (1U << 7) diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/iar/dpp-qk.ewp b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/iar/dpp-qk.ewp index 8b454f93..e046e2cf 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/iar/dpp-qk.ewp +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/iar/dpp-qk.ewp @@ -11,7 +11,7 @@ General 3 - 28 + 31 1 1 + + + ICCARM 2 - 34 + 36 1 1 + + @@ -676,7 +697,7 @@ ILINK 0 - 20 + 23 1 1 + + + + + + @@ -1032,7 +1077,7 @@ General 3 - 28 + 31 1 0 + + + ICCARM 2 - 34 + 36 1 0 + + @@ -1697,7 +1763,7 @@ ILINK 0 - 20 + 23 1 0 + + + + + + @@ -2053,7 +2143,7 @@ General 3 - 28 + 31 1 1 + + + ICCARM 2 - 34 + 36 1 1 + + @@ -2718,7 +2829,7 @@ ILINK 0 - 20 + 23 1 1 + + + + + + @@ -3160,10 +3295,10 @@ $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qf_port.h - $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.h + $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.c - $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.c + $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.h $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qs_port.h diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qv/bsp.c b/examples/arm-cm/dpp_ek-tm4c123gxl/qv/bsp.c index d6dcde30..19953fd0 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qv/bsp.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qv/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, EK-TM4C123GXL board, cooperative QV kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -65,9 +65,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIOPortA_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIOPortA_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE (1U << 7) diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.c b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.c index d1f76a62..80bb468a 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, EK-TM4C123GXL board, preemptive QXK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -63,9 +63,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS identifiers for non-QP sources of events */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIOPortA_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIOPortA_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE (1U << 7) diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.c b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.c index c196420c..038877fd 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.c @@ -82,7 +82,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/table.c b/examples/arm-cm/dpp_ek-tm4c123gxl/table.c index acf56b80..33f68997 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/table.c +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/table.c @@ -80,7 +80,6 @@ Table Table_inst; static QState Table_initial(Table * const me, void const * const par) { /*.${AOs::Table::SM::initial} */ uint8_t n; - (void)par; /* unused parameter */ QS_OBJ_DICTIONARY(&Table_inst); @@ -150,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -175,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -210,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -221,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_mbed-lpc1768/README.url b/examples/arm-cm/dpp_mbed-lpc1768/README.url index 4dfd607a..6516c353 100644 --- a/examples/arm-cm/dpp_mbed-lpc1768/README.url +++ b/examples/arm-cm/dpp_mbed-lpc1768/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_dpp_mbed-lpc1768.html +URL=https://www.state-machine.com/qpc/arm-cm_dpp_mbed-lpc1768.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/dpp_mbed-lpc1768/dpp.qm b/examples/arm-cm/dpp_mbed-lpc1768/dpp.qm index 646d8cda..61cec11e 100644 --- a/examples/arm-cm/dpp_mbed-lpc1768/dpp.qm +++ b/examples/arm-cm/dpp_mbed-lpc1768/dpp.qm @@ -105,7 +105,7 @@ Q_ASSERT_ID(20, Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); @@ -187,7 +187,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -210,7 +210,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -252,7 +252,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -263,7 +263,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } @@ -437,7 +437,8 @@ $define${AOs::AO_Philo[N_PHILO]} /* Philo definition --------------------------------------------------------*/ $define${AOs::Philo_ctor} -$define${AOs::Philo} +$define${AOs::Philo} + @@ -463,7 +464,8 @@ $define${AOs::AO_Table} /*..........................................................................*/ $define${AOs::Table_ctor} -$define${AOs::Table} +$define${AOs::Table} + diff --git a/examples/arm-cm/dpp_mbed-lpc1768/philo.c b/examples/arm-cm/dpp_mbed-lpc1768/philo.c index 54c47354..cd99e60f 100644 --- a/examples/arm-cm/dpp_mbed-lpc1768/philo.c +++ b/examples/arm-cm/dpp_mbed-lpc1768/philo.c @@ -199,7 +199,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); status_ = Q_HANDLED(); break; diff --git a/examples/arm-cm/dpp_mbed-lpc1768/qk/bsp.c b/examples/arm-cm/dpp_mbed-lpc1768/qk/bsp.c index 4164d968..4003d394 100644 --- a/examples/arm-cm/dpp_mbed-lpc1768/qk/bsp.c +++ b/examples/arm-cm/dpp_mbed-lpc1768/qk/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NXP mbed-LPC1768 board, QK kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -60,9 +60,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t l_SysTick_Handler; - static uint8_t l_EINT0_IRQHandler; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_EINT0_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE 0x80U diff --git a/examples/arm-cm/dpp_mbed-lpc1768/qv/bsp.c b/examples/arm-cm/dpp_mbed-lpc1768/qv/bsp.c index dbe14c61..cea832b5 100644 --- a/examples/arm-cm/dpp_mbed-lpc1768/qv/bsp.c +++ b/examples/arm-cm/dpp_mbed-lpc1768/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NXP mbed-LPC1768 board, coopearative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -60,9 +60,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t l_SysTick_Handler; - static uint8_t l_EINT0_IRQHandler; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_EINT0_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE 0x80U diff --git a/examples/arm-cm/dpp_mbed-lpc1768/table.c b/examples/arm-cm/dpp_mbed-lpc1768/table.c index ef9f9043..af075d69 100644 --- a/examples/arm-cm/dpp_mbed-lpc1768/table.c +++ b/examples/arm-cm/dpp_mbed-lpc1768/table.c @@ -146,7 +146,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -171,7 +171,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -206,7 +206,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -217,7 +217,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_nucleo-h743zi/dpp.qm b/examples/arm-cm/dpp_nucleo-h743zi/dpp.qm index 2ac9aa73..43ad83c4 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/dpp.qm +++ b/examples/arm-cm/dpp_nucleo-h743zi/dpp.qm @@ -119,7 +119,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -212,7 +212,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -235,7 +235,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -277,7 +277,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -288,7 +288,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_nucleo-h743zi/philo.c b/examples/arm-cm/dpp_nucleo-h743zi/philo.c index c9c9adfe..2210d649 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/philo.c +++ b/examples/arm-cm/dpp_nucleo-h743zi/philo.c @@ -205,7 +205,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_nucleo-h743zi/qk/bsp.c b/examples/arm-cm/dpp_nucleo-h743zi/qk/bsp.c index 5d98288b..713bb84d 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/qk/bsp.c +++ b/examples/arm-cm/dpp_nucleo-h743zi/qk/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NUCLEO-H743ZI board, preemptive QK kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -54,9 +54,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_EXTI0_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_EXTI0_IRQHandler = { 0U }; + static UART_HandleTypeDef l_uartHandle; enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_nucleo-h743zi/qv/bsp.c b/examples/arm-cm/dpp_nucleo-h743zi/qv/bsp.c index f2df54e1..4eea11f0 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/qv/bsp.c +++ b/examples/arm-cm/dpp_nucleo-h743zi/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NUCLEO-H743ZI board, cooperative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -56,9 +56,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static UART_HandleTypeDef l_uartHandle; enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_nucleo-h743zi/qxk/bsp.c b/examples/arm-cm/dpp_nucleo-h743zi/qxk/bsp.c index 48d1d8f6..5597f395 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/qxk/bsp.c +++ b/examples/arm-cm/dpp_nucleo-h743zi/qxk/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NUCLEO-H743ZI board, dual-mode QXK kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -54,9 +54,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_EXTI0_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_EXTI0_IRQHandler = { 0U }; + static UART_HandleTypeDef l_uartHandle; enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_nucleo-h743zi/qxk/test.c b/examples/arm-cm/dpp_nucleo-h743zi/qxk/test.c index 0f5dd8bb..94a27118 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/qxk/test.c +++ b/examples/arm-cm/dpp_nucleo-h743zi/qxk/test.c @@ -88,7 +88,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_nucleo-h743zi/table.c b/examples/arm-cm/dpp_nucleo-h743zi/table.c index 66747a1a..33f68997 100644 --- a/examples/arm-cm/dpp_nucleo-h743zi/table.c +++ b/examples/arm-cm/dpp_nucleo-h743zi/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_nucleo-l053r8/README.url b/examples/arm-cm/dpp_nucleo-l053r8/README.url index 2d76939f..e12278c5 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/README.url +++ b/examples/arm-cm/dpp_nucleo-l053r8/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_dpp_nucleo-l053r8.html +URL=https://www.state-machine.com/qpc/arm-cm_dpp_nucleo-l053r8.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/dpp_nucleo-l053r8/dpp.qm b/examples/arm-cm/dpp_nucleo-l053r8/dpp.qm index 2ac9aa73..43ad83c4 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/dpp.qm +++ b/examples/arm-cm/dpp_nucleo-l053r8/dpp.qm @@ -119,7 +119,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -212,7 +212,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -235,7 +235,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -277,7 +277,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -288,7 +288,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_nucleo-l053r8/philo.c b/examples/arm-cm/dpp_nucleo-l053r8/philo.c index c9c9adfe..2210d649 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/philo.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/philo.c @@ -205,7 +205,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.c b/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.c index 58191595..465c26e2 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, NUCLEO-L053R8 board, preemptive QK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -53,8 +53,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu_with-stack-prot/bsp_stack-prot.c b/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu_with-stack-prot/bsp_stack-prot.c index 4988d0ca..b463c8ec 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu_with-stack-prot/bsp_stack-prot.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu_with-stack-prot/bsp_stack-prot.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NUCLEO-L053R8 board, preemptive QK kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -57,8 +57,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qv/bsp.c b/examples/arm-cm/dpp_nucleo-l053r8/qv/bsp.c index bb5fbe14..e31ccac6 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qv/bsp.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/qv/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, NUCLEO-L053R8 board, cooperative QV kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -53,8 +53,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.c b/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.c index 961b7452..be9cebc2 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, NUCLEO-L053R8 board, preemptive QXK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -53,8 +53,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.c b/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.c index c196420c..038877fd 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.c @@ -82,7 +82,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_nucleo-l053r8/table.c b/examples/arm-cm/dpp_nucleo-l053r8/table.c index 66747a1a..33f68997 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/table.c +++ b/examples/arm-cm/dpp_nucleo-l053r8/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_nucleo-l152re/README.url b/examples/arm-cm/dpp_nucleo-l152re/README.url index 59159971..745f48d4 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/README.url +++ b/examples/arm-cm/dpp_nucleo-l152re/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_dpp_nucleo-l152re.html +URL=https://www.state-machine.com/qpc/arm-cm_dpp_nucleo-l152re.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/dpp_nucleo-l152re/dpp.qm b/examples/arm-cm/dpp_nucleo-l152re/dpp.qm index 2ac9aa73..43ad83c4 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/dpp.qm +++ b/examples/arm-cm/dpp_nucleo-l152re/dpp.qm @@ -119,7 +119,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -212,7 +212,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -235,7 +235,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -277,7 +277,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -288,7 +288,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_nucleo-l152re/philo.c b/examples/arm-cm/dpp_nucleo-l152re/philo.c index c9c9adfe..2210d649 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/philo.c +++ b/examples/arm-cm/dpp_nucleo-l152re/philo.c @@ -205,7 +205,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_nucleo-l152re/qk/bsp.c b/examples/arm-cm/dpp_nucleo-l152re/qk/bsp.c index 423a912a..ecb5df01 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/qk/bsp.c +++ b/examples/arm-cm/dpp_nucleo-l152re/qk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, STM32 NUCLEO-L152RE board, preemptive QK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -53,8 +53,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER diff --git a/examples/arm-cm/dpp_nucleo-l152re/qv/bsp.c b/examples/arm-cm/dpp_nucleo-l152re/qv/bsp.c index 9862f1ea..86663cbd 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/qv/bsp.c +++ b/examples/arm-cm/dpp_nucleo-l152re/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, STM32 NUCLEO-L152RE board, cooperative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -53,8 +53,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER diff --git a/examples/arm-cm/dpp_nucleo-l152re/qxk/bsp.c b/examples/arm-cm/dpp_nucleo-l152re/qxk/bsp.c index 86e0b96d..23570e9f 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/qxk/bsp.c +++ b/examples/arm-cm/dpp_nucleo-l152re/qxk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, STM32 NUCLEO-L152RE board, preemptive QXK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -53,8 +53,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick_Handler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER diff --git a/examples/arm-cm/dpp_nucleo-l152re/qxk/test.c b/examples/arm-cm/dpp_nucleo-l152re/qxk/test.c index c196420c..038877fd 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/qxk/test.c +++ b/examples/arm-cm/dpp_nucleo-l152re/qxk/test.c @@ -82,7 +82,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_nucleo-l152re/table.c b/examples/arm-cm/dpp_nucleo-l152re/table.c index 66747a1a..33f68997 100644 --- a/examples/arm-cm/dpp_nucleo-l152re/table.c +++ b/examples/arm-cm/dpp_nucleo-l152re/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_stm32f4-discovery/dpp.qm b/examples/arm-cm/dpp_stm32f4-discovery/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/dpp.qm +++ b/examples/arm-cm/dpp_stm32f4-discovery/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_stm32f4-discovery/philo.c b/examples/arm-cm/dpp_stm32f4-discovery/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/philo.c +++ b/examples/arm-cm/dpp_stm32f4-discovery/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.c b/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.c index f00ebae8..4ea0b257 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.c +++ b/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: "DPP" example on STM32F4-Discovery board, preemptive QK kernel -* Last Updated for Version: 6.9.2a -* Date of the Last Update: 2021-01-31 +* Last Updated for Version: 6.9.3 +* Date of the Last Update: 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -67,8 +67,8 @@ static uint32_t l_rnd; /* random seed */ static QSTimeCtr QS_tickTime_; static QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick; + /* QSpy source IDs */ + static QSpyId const l_SysTick = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qv/bsp.c b/examples/arm-cm/dpp_stm32f4-discovery/qv/bsp.c index 1713ffc8..b68c644e 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qv/bsp.c +++ b/examples/arm-cm/dpp_stm32f4-discovery/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: "DPP" example on STM32F4-Discovery board, cooperative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -67,8 +67,8 @@ static uint32_t l_rnd; /* random seed */ static QSTimeCtr QS_tickTime_; static QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick; + /* QSpy source IDs */ + static QSpyId const l_SysTick = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.c b/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.c index 6c90bbbc..e3302297 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.c +++ b/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: "DPP" example on STM32F4-Discovery board, dual-mode QXK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -67,8 +67,8 @@ static uint32_t l_rnd; /* random seed */ static QSTimeCtr QS_tickTime_; static QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_SysTick; + /* QSpy source IDs */ + static QSpyId const l_SysTick = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.c b/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.c index fb5d4093..7874322e 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.c +++ b/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.c @@ -88,7 +88,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_stm32f4-discovery/table.c b/examples/arm-cm/dpp_stm32f4-discovery/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/table.c +++ b/examples/arm-cm/dpp_stm32f4-discovery/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/dpp.qm b/examples/arm-cm/dpp_stm32f746g-discovery/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/dpp.qm +++ b/examples/arm-cm/dpp_stm32f746g-discovery/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/philo.c b/examples/arm-cm/dpp_stm32f746g-discovery/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/philo.c +++ b/examples/arm-cm/dpp_stm32f746g-discovery/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.c b/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.c index cfdc791d..084bc309 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.c +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, STM32746G-Discovery board, preemptive QK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -55,9 +55,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static UART_HandleTypeDef l_uartHandle; enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qv/bsp.c b/examples/arm-cm/dpp_stm32f746g-discovery/qv/bsp.c index ec1a769b..decf358e 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qv/bsp.c +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, STM32746G-Discovery board, cooperative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -55,9 +55,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static UART_HandleTypeDef l_uartHandle; enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.c b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.c index 4bd3902b..34dd15d6 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.c +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.c @@ -1,7 +1,7 @@ /***************************************************************************** * Product: DPP example, STM32746G-Discovery board, dual-mode QXK kernel -* Last updated for version 6.9.2a -* Last updated on 2021-01-31 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ @@ -55,9 +55,10 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_EXTI0_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_EXTI0_IRQHandler = { 0U }; + static UART_HandleTypeDef l_uartHandle; enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.c b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.c index fb5d4093..7874322e 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.c +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.c @@ -88,7 +88,7 @@ static void Thread1_run(QXThread * const me) { QXThread_delay(BSP_TICKS_PER_SEC/7); /* BLOCK */ /* publish to thread2 */ - //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1); + //QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1.super); /* test TLS */ lib_fun(1U); diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/table.c b/examples/arm-cm/dpp_stm32f746g-discovery/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/table.c +++ b/examples/arm-cm/dpp_stm32f746g-discovery/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm-cm/game_efm32-slstk3401a/README.url b/examples/arm-cm/game_efm32-slstk3401a/README.url index 16b6d673..1264c7e5 100644 --- a/examples/arm-cm/game_efm32-slstk3401a/README.url +++ b/examples/arm-cm/game_efm32-slstk3401a/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm-cm_game_efm32-slstk3401a.html +URL=https://www.state-machine.com/qpc/arm-cm_game_efm32-slstk3401a.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.c b/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.c index 41e3adfd..a3aa129f 100644 --- a/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.c +++ b/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.c @@ -74,9 +74,10 @@ static void paintBitsClear(uint8_t x, uint8_t y, QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL)); enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/game_efm32-slstk3401a/qv/bsp.c b/examples/arm-cm/game_efm32-slstk3401a/qv/bsp.c index b1e947e0..9c04123e 100644 --- a/examples/arm-cm/game_efm32-slstk3401a/qv/bsp.c +++ b/examples/arm-cm/game_efm32-slstk3401a/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: "Fly 'n' Shoot" game example, EFM32-SLSTK3401A board, QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -73,9 +73,10 @@ static void paintBitsClear(uint8_t x, uint8_t y, QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* QS source IDs */ - static uint8_t const l_SysTick_Handler = 0U; - static uint8_t const l_GPIO_EVEN_IRQHandler = 0U; + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; + static QSpyId const l_GPIO_EVEN_IRQHandler = { 0U }; + static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL)); enum AppRecords { /* application-specific trace records */ diff --git a/examples/arm-cm/low-power_ek-tm4c123gxl/qk/bsp.c b/examples/arm-cm/low-power_ek-tm4c123gxl/qk/bsp.c index 6ba3faa9..3a9cd29e 100644 --- a/examples/arm-cm/low-power_ek-tm4c123gxl/qk/bsp.c +++ b/examples/arm-cm/low-power_ek-tm4c123gxl/qk/bsp.c @@ -90,7 +90,7 @@ void GPIOPortF_IRQHandler(void) { QK_ISR_ENTRY(); /* inform QK about entering an ISR */ if ((GPIOF->RIS & BTN_SW1) != 0U) { /* interrupt caused by SW1? */ static QEvt const pressedEvt = { BTN_PRESSED_SIG, 0U, 0U}; - QF_PUBLISH(&pressedEvt, &l_SysTick_Handler); + QF_PUBLISH(&pressedEvt, (void *)0); } GPIOF->ICR = 0xFFU; /* clear interrupt sources */ QK_ISR_EXIT(); /* inform QK about exiting an ISR */ diff --git a/examples/arm-cm/low-power_ek-tm4c123gxl/qv/bsp.c b/examples/arm-cm/low-power_ek-tm4c123gxl/qv/bsp.c index 10623ea7..841786ad 100644 --- a/examples/arm-cm/low-power_ek-tm4c123gxl/qv/bsp.c +++ b/examples/arm-cm/low-power_ek-tm4c123gxl/qv/bsp.c @@ -86,7 +86,7 @@ void Timer0A_IRQHandler(void) { void GPIOPortF_IRQHandler(void) { if ((GPIOF->RIS & BTN_SW1) != 0U) { /* interrupt caused by SW1? */ static QEvt const pressedEvt = { BTN_PRESSED_SIG, 0U, 0U}; - QF_PUBLISH(&pressedEvt, &l_SysTick_Handler); + QF_PUBLISH(&pressedEvt, (void *)0); } GPIOF->ICR = 0xFFU; /* clear interrupt sources */ QV_ARM_ERRATUM_838869(); diff --git a/examples/arm-cm/low-power_ek-tm4c123gxl/qxk/bsp.c b/examples/arm-cm/low-power_ek-tm4c123gxl/qxk/bsp.c index 02ef19c1..7aaaa0fb 100644 --- a/examples/arm-cm/low-power_ek-tm4c123gxl/qxk/bsp.c +++ b/examples/arm-cm/low-power_ek-tm4c123gxl/qxk/bsp.c @@ -90,7 +90,7 @@ void GPIOPortF_IRQHandler(void) { QXK_ISR_ENTRY(); /* inform QXK about entering an ISR */ if ((GPIOF->RIS & BTN_SW1) != 0U) { /* interrupt caused by SW1? */ static QEvt const pressedEvt = { BTN_PRESSED_SIG, 0U, 0U}; - QF_PUBLISH(&pressedEvt, &l_SysTick_Handler); + QF_PUBLISH(&pressedEvt, (void *)0); QXSemaphore_signal(&XSEM_sw1); } GPIOF->ICR = 0xFFU; /* clear interrupt sources */ diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/dpp.qm b/examples/arm-cr/dpp_launchxl2-tms57012/dpp.qm index 2ac9aa73..43ad83c4 100644 --- a/examples/arm-cr/dpp_launchxl2-tms57012/dpp.qm +++ b/examples/arm-cr/dpp_launchxl2-tms57012/dpp.qm @@ -119,7 +119,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -212,7 +212,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -235,7 +235,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -277,7 +277,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -288,7 +288,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/philo.c b/examples/arm-cr/dpp_launchxl2-tms57012/philo.c index c9c9adfe..2210d649 100644 --- a/examples/arm-cr/dpp_launchxl2-tms57012/philo.c +++ b/examples/arm-cr/dpp_launchxl2-tms57012/philo.c @@ -205,7 +205,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.c b/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.c index 1f1faf88..0dfbe474 100644 --- a/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.c +++ b/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.c @@ -71,9 +71,9 @@ static uint32_t l_rnd; /* random seed */ #ifdef Q_SPY - /* QS source IDs */ - static uint8_t const l_rtiCompare0 = 0U; - static uint8_t const l_ssiTest = 0U; + /* QSpy source IDs */ + static QSpyId const l_rtiCompare0 = { 0U }; + static QSpyId const l_ssiTest = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/qv/bsp.c b/examples/arm-cr/dpp_launchxl2-tms57012/qv/bsp.c index 4f848c6e..c5c9d6bd 100644 --- a/examples/arm-cr/dpp_launchxl2-tms57012/qv/bsp.c +++ b/examples/arm-cr/dpp_launchxl2-tms57012/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: "DPP" on LAUCHXL2-TMS570LS12 board, cooperative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -71,9 +71,9 @@ static uint32_t l_rnd; /* random seed */ #ifdef Q_SPY - /* QS source IDs */ - static uint8_t const l_rtiCompare0 = 0U; - static uint8_t const l_ssiTest = 0U; + /* QSpy source IDs */ + static QSpyId const l_rtiCompare0 = { 0U }; + static QSpyId const l_ssiTest = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/table.c b/examples/arm-cr/dpp_launchxl2-tms57012/table.c index 66747a1a..33f68997 100644 --- a/examples/arm-cr/dpp_launchxl2-tms57012/table.c +++ b/examples/arm-cr/dpp_launchxl2-tms57012/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/arm7-9/README.url b/examples/arm7-9/README.url index 1f3ed9a4..59d7a3cf 100644 --- a/examples/arm7-9/README.url +++ b/examples/arm7-9/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_arm7-9.html +URL=https://www.state-machine.com/qpc/exa_arm7-9.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm7-9/dpp_at91sam7s-ek/README.url b/examples/arm7-9/dpp_at91sam7s-ek/README.url index 6655f8cb..2633528c 100644 --- a/examples/arm7-9/dpp_at91sam7s-ek/README.url +++ b/examples/arm7-9/dpp_at91sam7s-ek/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm7-9_dpp_at91sam7s-ek.html +URL=https://www.state-machine.com/qpc/arm7-9_dpp_at91sam7s-ek.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/arm7-9/dpp_at91sam7s-ek/dpp.qm b/examples/arm7-9/dpp_at91sam7s-ek/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/arm7-9/dpp_at91sam7s-ek/dpp.qm +++ b/examples/arm7-9/dpp_at91sam7s-ek/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/arm7-9/dpp_at91sam7s-ek/philo.c b/examples/arm7-9/dpp_at91sam7s-ek/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/arm7-9/dpp_at91sam7s-ek/philo.c +++ b/examples/arm7-9/dpp_at91sam7s-ek/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/arm7-9/dpp_at91sam7s-ek/qk/iar/bsp.c b/examples/arm7-9/dpp_at91sam7s-ek/qk/iar/bsp.c index ab0cc7dd..812ea161 100644 --- a/examples/arm7-9/dpp_at91sam7s-ek/qk/iar/bsp.c +++ b/examples/arm7-9/dpp_at91sam7s-ek/qk/iar/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP on AT91SAM7S-EK, QK kernel, IAR-ARM -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -68,7 +68,9 @@ static unsigned l_rnd; /* random seed */ #ifdef Q_SPY - static uint8_t const l_ISR_tick = 0; + /* QSpy source IDs */ + static QSpyId const l_ISR_tick = { 0U }; + enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER }; diff --git a/examples/arm7-9/dpp_at91sam7s-ek/qv/iar/bsp.c b/examples/arm7-9/dpp_at91sam7s-ek/qv/iar/bsp.c index a0299c43..5deb0180 100644 --- a/examples/arm7-9/dpp_at91sam7s-ek/qv/iar/bsp.c +++ b/examples/arm7-9/dpp_at91sam7s-ek/qv/iar/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP on AT91SAM7S-EK, QK kernel, IAR-ARM -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -68,7 +68,9 @@ static unsigned l_rnd; /* random seed */ #ifdef Q_SPY - static uint8_t const l_ISR_tick = 0; + /* QSpy source IDs */ + static QSpyId const l_ISR_tick = { 0U }; + enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER }; diff --git a/examples/arm7-9/dpp_at91sam7s-ek/table.c b/examples/arm7-9/dpp_at91sam7s-ek/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/arm7-9/dpp_at91sam7s-ek/table.c +++ b/examples/arm7-9/dpp_at91sam7s-ek/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/embos/README.url b/examples/embos/README.url index c2b5fb91..124fb05c 100644 --- a/examples/embos/README.url +++ b/examples/embos/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_embos.html +URL=https://www.state-machine.com/qpc/exa_embos.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/embos/arm-cm/dpp_stm32f429-discovery/README.url b/examples/embos/arm-cm/dpp_stm32f429-discovery/README.url index 89de02c9..9c056649 100644 --- a/examples/embos/arm-cm/dpp_stm32f429-discovery/README.url +++ b/examples/embos/arm-cm/dpp_stm32f429-discovery/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/embos_dpp_stm32f429-discovery.html +URL=https://www.state-machine.com/qpc/embos_dpp_stm32f429-discovery.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/embos/arm-cm/dpp_stm32f429-discovery/bsp.c b/examples/embos/arm-cm/dpp_stm32f429-discovery/bsp.c index 9fe15574..abd49596 100644 --- a/examples/embos/arm-cm/dpp_stm32f429-discovery/bsp.c +++ b/examples/embos/arm-cm/dpp_stm32f429-discovery/bsp.c @@ -61,7 +61,7 @@ static uint32_t l_rnd; /* random seed */ #ifdef Q_SPY /* event-source identifiers used for tracing */ - static uint8_t const l_embos_ticker = 0U; + static QSpyId const l_embos_ticker = { 0U }; QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; diff --git a/examples/embos/arm-cm/dpp_stm32f429-discovery/dpp.qm b/examples/embos/arm-cm/dpp_stm32f429-discovery/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/embos/arm-cm/dpp_stm32f429-discovery/dpp.qm +++ b/examples/embos/arm-cm/dpp_stm32f429-discovery/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/embos/arm-cm/dpp_stm32f429-discovery/main.c b/examples/embos/arm-cm/dpp_stm32f429-discovery/main.c index f35bebea..fe9af9ac 100644 --- a/examples/embos/arm-cm/dpp_stm32f429-discovery/main.c +++ b/examples/embos/arm-cm/dpp_stm32f429-discovery/main.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: "Dining Philosophers Problem" example, embOS -* Last updated for version 6.4.0 -* Last updated on 2019-02-08 +* Last updated for version 6.9.3 +* Last updated on 2021-04-09 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2019 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -63,13 +63,15 @@ int main() { /* start the active objects... */ for (n = 0U; n < N_PHILO; ++n) { + QActive_setAttr(AO_Philo[n], TASK_NAME_ATTR, "Philo"); QACTIVE_START(AO_Philo[n], (uint8_t)(n + 1), philoQueueSto[n], Q_DIM(philoQueueSto[n]), philoStack[n], sizeof(philoStack[n]), (QEvt *)0); } /* set the embOS task attributes BEFORE calling QACTIVE_START() */ - QActive_setAttr(AO_Table, QF_TASK_USES_FPU, 0); + QActive_setAttr(AO_Table, TASK_USES_FPU, 0); + QActive_setAttr(AO_Table, TASK_NAME_ATTR, "Table"); QACTIVE_START(AO_Table, (uint8_t)(N_PHILO + 1), tableQueueSto, Q_DIM(tableQueueSto), tableStack, sizeof(tableStack), (QEvt *)0); diff --git a/examples/embos/arm-cm/dpp_stm32f429-discovery/philo.c b/examples/embos/arm-cm/dpp_stm32f429-discovery/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/embos/arm-cm/dpp_stm32f429-discovery/philo.c +++ b/examples/embos/arm-cm/dpp_stm32f429-discovery/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/embos/arm-cm/dpp_stm32f429-discovery/table.c b/examples/embos/arm-cm/dpp_stm32f429-discovery/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/embos/arm-cm/dpp_stm32f429-discovery/table.c +++ b/examples/embos/arm-cm/dpp_stm32f429-discovery/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/emwin/README.url b/examples/emwin/README.url index 2ea3288d..5483d059 100644 --- a/examples/emwin/README.url +++ b/examples/emwin/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_emwin.html +URL=https://www.state-machine.com/qpc/exa_emwin.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/emwin/demo_no_wm/philo.c b/examples/emwin/demo_no_wm/philo.c index 42d1a1df..4815d89c 100644 --- a/examples/emwin/demo_no_wm/philo.c +++ b/examples/emwin/demo_no_wm/philo.c @@ -159,7 +159,7 @@ QState Philo_eating(Philo *me, QEvt const *e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); return Q_HANDLED(); } case TIMEOUT_SIG: { diff --git a/examples/emwin/demo_no_wm/table.c b/examples/emwin/demo_no_wm/table.c index 4a410d18..6e64bc5d 100644 --- a/examples/emwin/demo_no_wm/table.c +++ b/examples/emwin/demo_no_wm/table.c @@ -231,7 +231,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->fork[LEFT(n)] = me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); me->isHungry[n] = 0; displyPhilStat(n, "eating "); } @@ -247,7 +247,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->fork[m] = me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); displyPhilStat(n, "eating "); } else { @@ -266,7 +266,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->isHungry[m] = 0; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); displyPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -276,7 +276,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->isHungry[m] = 0; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); displyPhilStat(m, "eating "); } return Q_HANDLED(); diff --git a/examples/emwin/demo_with_wm/philo.c b/examples/emwin/demo_with_wm/philo.c index 42d1a1df..4815d89c 100644 --- a/examples/emwin/demo_with_wm/philo.c +++ b/examples/emwin/demo_with_wm/philo.c @@ -159,7 +159,7 @@ QState Philo_eating(Philo *me, QEvt const *e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); return Q_HANDLED(); } case TIMEOUT_SIG: { diff --git a/examples/emwin/demo_with_wm/table.c b/examples/emwin/demo_with_wm/table.c index 5e1c1b98..8786c9e2 100644 --- a/examples/emwin/demo_with_wm/table.c +++ b/examples/emwin/demo_with_wm/table.c @@ -257,7 +257,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->fork[LEFT(n)] = me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); me->isHungry[n] = 0; displyPhilStat(n, "eating "); } @@ -273,7 +273,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->fork[m] = me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); displyPhilStat(n, "eating "); } else { @@ -292,7 +292,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->isHungry[m] = 0; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); displyPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -302,7 +302,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->isHungry[m] = 0; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); displyPhilStat(m, "eating "); } return Q_HANDLED(); diff --git a/examples/freertos/README.url b/examples/freertos/README.url index 62c2facd..f6037edf 100644 --- a/examples/freertos/README.url +++ b/examples/freertos/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_freertos.html +URL=https://www.state-machine.com/qpc/exa_freertos.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.url b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.url index 7ee21977..0eadd3c0 100644 --- a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.url +++ b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/freertos_dpp_ek-tm4c123gxl.html +URL=https://www.state-machine.com/qpc/freertos_dpp_ek-tm4c123gxl.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/dpp.qm b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/dpp.qm +++ b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/philo.c b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/philo.c +++ b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/table.c b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/table.c +++ b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/freertos/arm-cm/dpp_nucleo-h743zi/dpp.qm b/examples/freertos/arm-cm/dpp_nucleo-h743zi/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/freertos/arm-cm/dpp_nucleo-h743zi/dpp.qm +++ b/examples/freertos/arm-cm/dpp_nucleo-h743zi/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/freertos/arm-cm/dpp_nucleo-h743zi/philo.c b/examples/freertos/arm-cm/dpp_nucleo-h743zi/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/freertos/arm-cm/dpp_nucleo-h743zi/philo.c +++ b/examples/freertos/arm-cm/dpp_nucleo-h743zi/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/freertos/arm-cm/dpp_nucleo-h743zi/table.c b/examples/freertos/arm-cm/dpp_nucleo-h743zi/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/freertos/arm-cm/dpp_nucleo-h743zi/table.c +++ b/examples/freertos/arm-cm/dpp_nucleo-h743zi/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/freertos/arm-cm/dpp_stm32f746g-discovery/dpp.qm b/examples/freertos/arm-cm/dpp_stm32f746g-discovery/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/freertos/arm-cm/dpp_stm32f746g-discovery/dpp.qm +++ b/examples/freertos/arm-cm/dpp_stm32f746g-discovery/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/freertos/arm-cm/dpp_stm32f746g-discovery/philo.c b/examples/freertos/arm-cm/dpp_stm32f746g-discovery/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/freertos/arm-cm/dpp_stm32f746g-discovery/philo.c +++ b/examples/freertos/arm-cm/dpp_stm32f746g-discovery/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/freertos/arm-cm/dpp_stm32f746g-discovery/table.c b/examples/freertos/arm-cm/dpp_stm32f746g-discovery/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/freertos/arm-cm/dpp_stm32f746g-discovery/table.c +++ b/examples/freertos/arm-cm/dpp_stm32f746g-discovery/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/lwip/README.url b/examples/lwip/README.url index 55774ed6..763e08be 100644 --- a/examples/lwip/README.url +++ b/examples/lwip/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_lwip.html +URL=https://www.state-machine.com/qpc/exa_lwip.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/lwip/arm-cm/lwip_ek-lm3s6965/README.url b/examples/lwip/arm-cm/lwip_ek-lm3s6965/README.url index df8a6314..017784bf 100644 --- a/examples/lwip/arm-cm/lwip_ek-lm3s6965/README.url +++ b/examples/lwip/arm-cm/lwip_ek-lm3s6965/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/lwip_ek-lm3s6965.html +URL=https://www.state-machine.com/qpc/lwip_ek-lm3s6965.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/lwip/arm-cm/lwip_ek-lm3s6965/lwipmgr.c b/examples/lwip/arm-cm/lwip_ek-lm3s6965/lwipmgr.c index cb15311e..e6965da6 100644 --- a/examples/lwip/arm-cm/lwip_ek-lm3s6965/lwipmgr.c +++ b/examples/lwip/arm-cm/lwip_ek-lm3s6965/lwipmgr.c @@ -228,7 +228,7 @@ QState LwIPMgr_running(LwIPMgr *me, QEvt const *e) { (int)(((ip_net) >> 16) & 0xFFU), (int)(((ip_net) >> 8) & 0xFFU), (int)(ip_net & 0xFFU)); - QF_PUBLISH((QEvt *)te, me); + QF_PUBLISH((QEvt *)te, &me->super); } #if LWIP_TCP diff --git a/examples/lwip/arm-cm/lwip_ek-lm3s6965/philo.c b/examples/lwip/arm-cm/lwip_ek-lm3s6965/philo.c index 283da459..c7cb16e0 100644 --- a/examples/lwip/arm-cm/lwip_ek-lm3s6965/philo.c +++ b/examples/lwip/arm-cm/lwip_ek-lm3s6965/philo.c @@ -162,7 +162,7 @@ QState Philo_eating(Philo *me, QEvt const *e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); return Q_HANDLED(); } case TIMEOUT_SIG: { diff --git a/examples/lwip/arm-cm/lwip_ek-lm3s6965/qk/bsp.c b/examples/lwip/arm-cm/lwip_ek-lm3s6965/qk/bsp.c index dfdb56aa..36a22414 100644 --- a/examples/lwip/arm-cm/lwip_ek-lm3s6965/qk/bsp.c +++ b/examples/lwip/arm-cm/lwip_ek-lm3s6965/qk/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP with lwIP application, preemptive QK kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -55,7 +55,9 @@ static uint32_t l_nTicks; QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - static uint8_t l_SysTick_Handler; + + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_TXFIFO_DEPTH 16U diff --git a/examples/lwip/arm-cm/lwip_ek-lm3s6965/qv/bsp.c b/examples/lwip/arm-cm/lwip_ek-lm3s6965/qv/bsp.c index a0ae01b2..36956773 100644 --- a/examples/lwip/arm-cm/lwip_ek-lm3s6965/qv/bsp.c +++ b/examples/lwip/arm-cm/lwip_ek-lm3s6965/qv/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP with lwIP application, cooperative QV kernel -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -55,7 +55,9 @@ static uint32_t l_nTicks; QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - static uint8_t l_SysTick_Handler; + + /* QSpy source IDs */ + static QSpyId const l_SysTick_Handler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_TXFIFO_DEPTH 16U diff --git a/examples/lwip/arm-cm/lwip_ek-lm3s6965/table.c b/examples/lwip/arm-cm/lwip_ek-lm3s6965/table.c index bf03a878..3f0728c4 100644 --- a/examples/lwip/arm-cm/lwip_ek-lm3s6965/table.c +++ b/examples/lwip/arm-cm/lwip_ek-lm3s6965/table.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example with lwIP and direct screen output -* Last updated for version 6.9.1 -* Last updated on 2020-09-11 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -35,7 +35,7 @@ #include "dpp.h" /* application events and active objects */ #include "bsp.h" /* Board Support Package header file */ -#include "rit128x96x4.h" /* RITEK 128x96x4 OLED used in Rev C-D boards */ +#include "rit128x96x4.h" /* RITEK 128x96x4 OLED used in Rev C-D boards */ #include /* for snprintf() */ @@ -159,7 +159,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->fork[m] = me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); Table_displayPhilStat(me, n, "eating "); } else { @@ -184,7 +184,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->isHungry[m] = 0; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); Table_displayPhilStat(me, m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -194,7 +194,7 @@ QState Table_serving(Table *me, QEvt const *e) { me->isHungry[m] = 0; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH((QEvt *)pe, me); + QF_PUBLISH((QEvt *)pe, &me->super); Table_displayPhilStat(me, m, "eating "); } return Q_HANDLED(); diff --git a/examples/msp430/README.url b/examples/msp430/README.url index 766ec349..03e52a7e 100644 --- a/examples/msp430/README.url +++ b/examples/msp430/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_msp430.html +URL=https://www.state-machine.com/qpc/exa_msp430.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/msp430/blinky_msp-exp430f5529lp/README.url b/examples/msp430/blinky_msp-exp430f5529lp/README.url index 668d72ab..57cfa3ca 100644 --- a/examples/msp430/blinky_msp-exp430f5529lp/README.url +++ b/examples/msp430/blinky_msp-exp430f5529lp/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/msp430_blinky_msp-exp430f5529lp.html +URL=https://www.state-machine.com/qpc/msp430_blinky_msp-exp430f5529lp.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/msp430/dpp_msp-exp430f5529lp/dpp.qm b/examples/msp430/dpp_msp-exp430f5529lp/dpp.qm index 6b8da014..b51f5938 100644 --- a/examples/msp430/dpp_msp-exp430f5529lp/dpp.qm +++ b/examples/msp430/dpp_msp-exp430f5529lp/dpp.qm @@ -108,7 +108,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -203,7 +203,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -226,7 +226,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -268,7 +268,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -279,7 +279,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/msp430/dpp_msp-exp430f5529lp/philo.c b/examples/msp430/dpp_msp-exp430f5529lp/philo.c index df49a49e..a9d78c3e 100644 --- a/examples/msp430/dpp_msp-exp430f5529lp/philo.c +++ b/examples/msp430/dpp_msp-exp430f5529lp/philo.c @@ -192,7 +192,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/msp430/dpp_msp-exp430f5529lp/table.c b/examples/msp430/dpp_msp-exp430f5529lp/table.c index 8f27e039..4fa7aee6 100644 --- a/examples/msp430/dpp_msp-exp430f5529lp/table.c +++ b/examples/msp430/dpp_msp-exp430f5529lp/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/pic24_dspic/dpp_microstick2-pic24/dpp.qm b/examples/pic24_dspic/dpp_microstick2-pic24/dpp.qm index 6b8da014..b51f5938 100644 --- a/examples/pic24_dspic/dpp_microstick2-pic24/dpp.qm +++ b/examples/pic24_dspic/dpp_microstick2-pic24/dpp.qm @@ -108,7 +108,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -203,7 +203,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -226,7 +226,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -268,7 +268,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -279,7 +279,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/pic24_dspic/dpp_microstick2-pic24/philo.c b/examples/pic24_dspic/dpp_microstick2-pic24/philo.c index df49a49e..a9d78c3e 100644 --- a/examples/pic24_dspic/dpp_microstick2-pic24/philo.c +++ b/examples/pic24_dspic/dpp_microstick2-pic24/philo.c @@ -192,7 +192,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/pic24_dspic/dpp_microstick2-pic24/table.c b/examples/pic24_dspic/dpp_microstick2-pic24/table.c index 8f27e039..4fa7aee6 100644 --- a/examples/pic24_dspic/dpp_microstick2-pic24/table.c +++ b/examples/pic24_dspic/dpp_microstick2-pic24/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/pic32/dpp_microstick2-pic32/dpp.qm b/examples/pic32/dpp_microstick2-pic32/dpp.qm index 6b8da014..b51f5938 100644 --- a/examples/pic32/dpp_microstick2-pic32/dpp.qm +++ b/examples/pic32/dpp_microstick2-pic32/dpp.qm @@ -108,7 +108,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -203,7 +203,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -226,7 +226,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -268,7 +268,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -279,7 +279,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/pic32/dpp_microstick2-pic32/philo.c b/examples/pic32/dpp_microstick2-pic32/philo.c index df49a49e..a9d78c3e 100644 --- a/examples/pic32/dpp_microstick2-pic32/philo.c +++ b/examples/pic32/dpp_microstick2-pic32/philo.c @@ -192,7 +192,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/pic32/dpp_microstick2-pic32/table.c b/examples/pic32/dpp_microstick2-pic32/table.c index 8f27e039..4fa7aee6 100644 --- a/examples/pic32/dpp_microstick2-pic32/table.c +++ b/examples/pic32/dpp_microstick2-pic32/table.c @@ -149,7 +149,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -174,7 +174,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -220,7 +220,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/qutest/dpp/dpp.qm b/examples/qutest/dpp/dpp.qm index 690a0e8a..0393be5a 100644 --- a/examples/qutest/dpp/dpp.qm +++ b/examples/qutest/dpp/dpp.qm @@ -103,7 +103,7 @@ Q_ASSERT_ID(20, Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); @@ -177,7 +177,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -200,7 +200,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -242,7 +242,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -253,7 +253,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/qutest/dpp/src/philo.c b/examples/qutest/dpp/src/philo.c index 398686d6..1fa0a260 100644 --- a/examples/qutest/dpp/src/philo.c +++ b/examples/qutest/dpp/src/philo.c @@ -197,7 +197,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); status_ = Q_HANDLED(); break; diff --git a/examples/qutest/dpp/src/table.c b/examples/qutest/dpp/src/table.c index 5df71aac..78425d02 100644 --- a/examples/qutest/dpp/src/table.c +++ b/examples/qutest/dpp/src/table.c @@ -138,7 +138,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -163,7 +163,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -198,7 +198,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -209,7 +209,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/threadx/README.url b/examples/threadx/README.url index 72bdfb3b..8bfd8b45 100644 --- a/examples/threadx/README.url +++ b/examples/threadx/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_threadx.html +URL=https://www.state-machine.com/qpc/exa_threadx.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.qm b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.qm index d91d06bd..61cec11e 100644 --- a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.qm +++ b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.qm @@ -105,7 +105,7 @@ Q_ASSERT_ID(20, Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); @@ -187,7 +187,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -210,7 +210,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -252,7 +252,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -263,7 +263,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewp b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewp index e010d232..0d1fc31d 100644 --- a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewp +++ b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewp @@ -66,7 +66,7 @@ + @@ -1007,7 +1011,7 @@ + @@ -2190,7 +2198,7 @@ + @@ -3190,7 +3202,6 @@ Debug Release - Spy Application @@ -3303,20 +3314,497 @@ ThreadX - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tm4c123xx_iar\readme_threadx.txt - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tm4c123xx_iar\tx.a - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_api.h - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tm4c123xx_iar\tx_port.h - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_trace.h - + + common + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_allocate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_cleanup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_release.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_initialize_high_level.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_initialize_kernel_enter.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_initialize_kernel_setup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_cleanup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_priority_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_cleanup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_flush.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_front_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_receive.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_send_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_entry_exit_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_identify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_preemption_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_priority_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_relinquish.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_reset.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_resume.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_shell_entry.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_sleep.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_stack_analyze.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_stack_error_handler.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_stack_error_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_suspend.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_system_preempt_check.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_system_resume.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_system_suspend.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_terminate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_time_slice.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_time_slice_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_timeout.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_wait_abort.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_time_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_time_set.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_activate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_deactivate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_expiration_process.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_system_activate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_system_deactivate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_thread_entry.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_buffer_full_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_disable.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_enable.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_event_filter.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_event_unfilter.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_interrupt_control.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_isr_enter_insert.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_isr_exit_insert.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_object_register.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_object_unregister.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_user_event_insert.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_allocate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_release.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_allocate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_release.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_set.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_set_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_flush.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_front_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_receive.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_send_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_ceiling_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_put_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_entry_exit_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_preemption_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_priority_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_relinquish.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_reset.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_resume.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_suspend.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_terminate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_time_slice_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_wait_abort.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_activate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_deactivate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_info_get.c + + + + port + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_iar.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_initialize_low_level.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_context_restore.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_context_save.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_interrupt_control.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_interrupt_disable.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_interrupt_restore.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_schedule.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_stack_build.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_system_return.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_timer_interrupt.s + + diff --git a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/main.c b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/main.c index d3d71043..38579e8b 100644 --- a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/main.c +++ b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/main.c @@ -1,12 +1,12 @@ /***************************************************************************** -* Last updated for version 6.9.0 -* Last updated on 2020-08-11 +* Last updated for version 6.9.3 +* Last updated on 2021-04-08 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -80,10 +80,13 @@ void tx_application_define(void *first_unused_memory) { QS_OBJ_DICTIONARY(l_philoQueueSto[4]); for (n = 0; n < N_PHILO; ++n) { /* start the active objects... */ + QActive_setAttr(AO_Philo[n], THREAD_NAME_ATTR, "Philo"); QACTIVE_START(AO_Philo[n], (uint8_t)(n + 1), l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]), l_philoStk[n], sizeof(l_philoStk[n]), (QEvt *)0); } + + QActive_setAttr(AO_Table, THREAD_NAME_ATTR, "Table"); QACTIVE_START(AO_Table, (uint8_t)(N_PHILO + 1), l_tableQueueSto, Q_DIM(l_tableQueueSto), l_tableStk, sizeof(l_tableStk), (QEvt *)0); diff --git a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/philo.c b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/philo.c index 54c47354..cd99e60f 100644 --- a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/philo.c +++ b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/philo.c @@ -199,7 +199,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); status_ = Q_HANDLED(); break; diff --git a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/table.c b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/table.c index ef9f9043..af075d69 100644 --- a/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/table.c +++ b/examples/threadx/arm-cm/dpp_ek-tm4c123gxl/table.c @@ -146,7 +146,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -171,7 +171,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -206,7 +206,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -217,7 +217,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/threadx/arm-cm/dpp_stm32f429-discovery/dpp.qm b/examples/threadx/arm-cm/dpp_stm32f429-discovery/dpp.qm index d91d06bd..61cec11e 100644 --- a/examples/threadx/arm-cm/dpp_stm32f429-discovery/dpp.qm +++ b/examples/threadx/arm-cm/dpp_stm32f429-discovery/dpp.qm @@ -105,7 +105,7 @@ Q_ASSERT_ID(20, Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); @@ -187,7 +187,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -210,7 +210,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -252,7 +252,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -263,7 +263,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/threadx/arm-cm/dpp_stm32f429-discovery/iar/dpp.ewp b/examples/threadx/arm-cm/dpp_stm32f429-discovery/iar/dpp.ewp index 6cec7d2a..ad2b43fa 100644 --- a/examples/threadx/arm-cm/dpp_stm32f429-discovery/iar/dpp.ewp +++ b/examples/threadx/arm-cm/dpp_stm32f429-discovery/iar/dpp.ewp @@ -11,7 +11,7 @@ General 3 - 30 + 31 1 1 + ICCARM 2 - 34 + 36 1 1 + + @@ -685,7 +698,7 @@ ILINK 0 - 20 + 23 1 1 + + + + + + @@ -1041,7 +1078,7 @@ General 3 - 30 + 31 1 0 + ICCARM 2 - 34 + 36 1 0 + + @@ -1715,7 +1765,7 @@ ILINK 0 - 20 + 23 1 0 + + + + + + @@ -2071,7 +2145,7 @@ General 3 - 30 + 31 1 1 + ICCARM 2 - 34 + 36 1 1 + + @@ -2745,7 +2832,7 @@ ILINK 0 - 20 + 23 1 1 + + + + + + @@ -3091,6 +3202,10 @@ + + Debug + Release + Application @@ -3217,20 +3332,494 @@ ThreadX - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar\readme_threadx.txt - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar\tx.a - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_api.h - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar\tx_port.h - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_trace.h - + + common + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_allocate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_cleanup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_pool_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_block_release.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_initialize_high_level.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_initialize_kernel_enter.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_initialize_kernel_setup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_cleanup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_priority_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_mutex_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_cleanup.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_flush.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_front_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_receive.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_queue_send_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_entry_exit_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_identify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_preemption_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_priority_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_relinquish.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_reset.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_resume.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_shell_entry.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_sleep.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_stack_analyze.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_stack_error_handler.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_stack_error_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_suspend.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_system_preempt_check.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_system_resume.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_system_suspend.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_terminate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_time_slice.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_time_slice_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_timeout.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_thread_wait_abort.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_time_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_time_set.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_activate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_deactivate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_expiration_process.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_performance_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_performance_system_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_system_activate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_system_deactivate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_timer_thread_entry.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_buffer_full_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_disable.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_enable.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_event_filter.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_event_unfilter.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_initialize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_interrupt_control.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_isr_enter_insert.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_isr_exit_insert.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_object_register.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_object_unregister.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\tx_trace_user_event_insert.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_allocate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_pool_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_block_release.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_allocate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_pool_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_byte_release.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_set.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_event_flags_set_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_mutex_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_flush.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_front_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_receive.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_send.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_queue_send_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_ceiling_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_prioritize.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_put.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_semaphore_put_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_entry_exit_notify.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_info_get.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_preemption_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_priority_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_relinquish.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_reset.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_resume.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_suspend.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_terminate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_time_slice_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_thread_wait_abort.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_activate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_change.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_create.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_deactivate.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_delete.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\common\src\txe_timer_info_get.c + + + + port + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_initialize_low_level.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_context_restore.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_context_save.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_interrupt_control.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_interrupt_disable.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_interrupt_restore.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_schedule.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_stack_build.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_thread_system_return.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\ports\cortex_m4\iar\src\tx_timer_interrupt.s + + diff --git a/examples/threadx/arm-cm/dpp_stm32f429-discovery/main.c b/examples/threadx/arm-cm/dpp_stm32f429-discovery/main.c index d3d71043..38579e8b 100644 --- a/examples/threadx/arm-cm/dpp_stm32f429-discovery/main.c +++ b/examples/threadx/arm-cm/dpp_stm32f429-discovery/main.c @@ -1,12 +1,12 @@ /***************************************************************************** -* Last updated for version 6.9.0 -* Last updated on 2020-08-11 +* Last updated for version 6.9.3 +* Last updated on 2021-04-08 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -80,10 +80,13 @@ void tx_application_define(void *first_unused_memory) { QS_OBJ_DICTIONARY(l_philoQueueSto[4]); for (n = 0; n < N_PHILO; ++n) { /* start the active objects... */ + QActive_setAttr(AO_Philo[n], THREAD_NAME_ATTR, "Philo"); QACTIVE_START(AO_Philo[n], (uint8_t)(n + 1), l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]), l_philoStk[n], sizeof(l_philoStk[n]), (QEvt *)0); } + + QActive_setAttr(AO_Table, THREAD_NAME_ATTR, "Table"); QACTIVE_START(AO_Table, (uint8_t)(N_PHILO + 1), l_tableQueueSto, Q_DIM(l_tableQueueSto), l_tableStk, sizeof(l_tableStk), (QEvt *)0); diff --git a/examples/threadx/arm-cm/dpp_stm32f429-discovery/philo.c b/examples/threadx/arm-cm/dpp_stm32f429-discovery/philo.c index 54c47354..cd99e60f 100644 --- a/examples/threadx/arm-cm/dpp_stm32f429-discovery/philo.c +++ b/examples/threadx/arm-cm/dpp_stm32f429-discovery/philo.c @@ -199,7 +199,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); QTimeEvt_disarm(&me->timeEvt); status_ = Q_HANDLED(); break; diff --git a/examples/threadx/arm-cm/dpp_stm32f429-discovery/table.c b/examples/threadx/arm-cm/dpp_stm32f429-discovery/table.c index ef9f9043..af075d69 100644 --- a/examples/threadx/arm-cm/dpp_stm32f429-discovery/table.c +++ b/examples/threadx/arm-cm/dpp_stm32f429-discovery/table.c @@ -146,7 +146,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -171,7 +171,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -206,7 +206,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -217,7 +217,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/ucos-ii/README.url b/examples/ucos-ii/README.url index b3de3340..a02eb988 100644 --- a/examples/ucos-ii/README.url +++ b/examples/ucos-ii/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/exa_ucos-ii.html +URL=https://www.state-machine.com/qpc/exa_ucos-ii.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/README.url b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/README.url index 49ed085d..aec0ecfe 100644 --- a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/README.url +++ b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/ucos-ii_dpp_ek-tm4c123gxl.html +URL=https://www.state-machine.com/qpc/ucos-ii_dpp_ek-tm4c123gxl.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/bsp.c b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/bsp.c index 8fc7f1cd..eac53fb5 100644 --- a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/bsp.c +++ b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, EK-TM4C123GLX board, uC/OS-II RTOS -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -59,9 +59,9 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t l_tickHook; - static uint8_t l_GPIOPortA_IRQHandler; + /* QSpy source IDs */ + static QSpyId const l_tickHook = { 0U }; + static QSpyId const l_GPIOPortA_IRQHandler = { 0U }; #define UART_BAUD_RATE 115200U #define UART_FR_TXFE 0x80U diff --git a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/dpp.qm b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/dpp.qm +++ b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/main.c b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/main.c index 47591cf4..161a0b64 100644 --- a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/main.c +++ b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/main.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, uC/OS-II -* Last updated for version 6.8.1 -* Last updated on 2020-06-08 +* Last updated for version 6.9.3 +* Last updated on 2021-04-08 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -70,24 +70,26 @@ int main() { for (n = 0U; n < N_PHILO; ++n) { /* NOTE: provide uC/OS-II task attributes for the AO's task */ QActive_setAttr(AO_Philo[n], OS_TASK_OPT_STK_CHK, 0); + QActive_setAttr(AO_Philo[n], TASK_NAME_ATTR, "Philo"); QACTIVE_START(AO_Philo[n], n + 1U, /* QP priority */ philoQueueSto[n], /* storage for the AO's queue */ Q_DIM(philoQueueSto[n]), /* queue's length [entries] */ philoStk[n], /* stack storage */ sizeof(philoStk[n]), /* sack size [bytes] */ - (QEvt const *)0); /* initialization event */ + (void *)0); /* initialization event */ } /* NOTE: provide uC/OS-II task attributes for the AO's task */ QActive_setAttr(AO_Table, OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK, 0); + QActive_setAttr(AO_Table, TASK_NAME_ATTR, "Table"); QACTIVE_START(AO_Table, N_PHILO + 1U, /* QP priority */ tableQueueSto, /* storage for the AO's queue */ Q_DIM(tableQueueSto), /* queue's length [entries] */ tableStk, /* stack storage */ sizeof(tableStk), /* sack size [bytes] */ - (QEvt const *)0); /* initialization event */ + (void *)0); /* initialization event */ return QF_run(); /* run the QF application */ } diff --git a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/philo.c b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/philo.c +++ b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/table.c b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/table.c +++ b/examples/ucos-ii/arm-cm/dpp_ek-tm4c123gxl/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/README.url b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/README.url index 49ed085d..aec0ecfe 100644 --- a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/README.url +++ b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/ucos-ii_dpp_ek-tm4c123gxl.html +URL=https://www.state-machine.com/qpc/ucos-ii_dpp_ek-tm4c123gxl.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/bsp.c b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/bsp.c index e201a740..eb2a2e98 100644 --- a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/bsp.c +++ b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example, NUCLEO-L053R8 board, uC/OS-II RTOS -* Last updated for version 6.9.1 -* Last updated on 2020-09-22 +* Last updated for version 6.9.3 +* Last updated on 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -54,8 +54,8 @@ static uint32_t l_rnd; /* random seed */ QSTimeCtr QS_tickTime_; QSTimeCtr QS_tickPeriod_; - /* event-source identifiers used for tracing */ - static uint8_t const l_tickHook = 0U; + /* QSpy source IDs */ + static QSpyId const l_tickHook = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, diff --git a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/dpp.qm b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/dpp.qm index 10224057..5b1603f1 100644 --- a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/dpp.qm +++ b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/dpp.qm @@ -116,7 +116,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -210,7 +210,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -233,7 +233,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -275,7 +275,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -286,7 +286,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/philo.c b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/philo.c index 2f28e54f..e6c85eb9 100644 --- a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/philo.c +++ b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/philo.c @@ -204,7 +204,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/table.c b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/table.c index 7ef12cea..39d09a9e 100644 --- a/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/table.c +++ b/examples/ucos-ii/arm-cm/dpp_nucleo-l053r8/table.c @@ -148,7 +148,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -173,7 +173,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -208,7 +208,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -219,7 +219,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/workstation/calc1/SM_of_Calc.png b/examples/workstation/calc1/SM_of_Calc.png new file mode 100644 index 00000000..d8995407 Binary files /dev/null and b/examples/workstation/calc1/SM_of_Calc.png differ diff --git a/examples/workstation/calc2/Makefile b/examples/workstation/calc2/Makefile new file mode 100644 index 00000000..deccb82b --- /dev/null +++ b/examples/workstation/calc2/Makefile @@ -0,0 +1,294 @@ +############################################################################## +# Product: Makefile for QP/C for Windows and POSIX *HOSTS* +# Last updated for version 6.9.3 +# Last updated on 2021-03-18 +# +# Q u a n t u m L e a P s +# ------------------------ +# Modern Embedded Software +# +# Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. +# +# This program is open source software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Alternatively, this program may be distributed and modified under the +# terms of Quantum Leaps commercial licenses, which expressly supersede +# the GNU General Public License and are specifically designed for +# licensees interested in retaining the proprietary status of their code. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Contact information: +# https://www.state-machine.com +# mailto:info@state-machine.com +############################################################################## +# +# examples of invoking this Makefile: +# building configurations: Debug (default), Release, and Spy +# make +# make CONF=rel +# make CONF=spy +# make clean # cleanup the build +# make CONF=spy clean # cleanup the build +# +# NOTE: +# To use this Makefile on Windows, you will need the GNU make utility, which +# is included in the QTools collection for Windows, see: +# http://sourceforge.net/projects/qpc/files/QTools/ +# + +#----------------------------------------------------------------------------- +# project name: +# +PROJECT := calc2 + +#----------------------------------------------------------------------------- +# project directories: +# + +# list of all source directories used by this project +VPATH := . \ + +# list of all include directories needed by this project +INCLUDES := -I. \ + +# location of the QP/C framework (if not provided in an env. variable) +ifeq ($(QPC),) +QPC := ../../.. +endif + +#----------------------------------------------------------------------------- +# project files: +# + +# C source files... +C_SRCS := \ + bsp.c \ + main.c \ + calc2.c + +# C++ source files... +CPP_SRCS := + +LIB_DIRS := +LIBS := + +# defines... +# QP_API_VERSION controls the QP API compatibility; 9999 means the latest API +DEFINES := -DQP_API_VERSION=9999 + +ifeq (,$(CONF)) + CONF := dbg +endif + +#----------------------------------------------------------------------------- +# add QP/C framework (depends on the OS this Makefile runs on): +# +ifeq ($(OS),Windows_NT) + +# NOTE: +# For Windows hosts, you can choose: +# - the single-threaded QP/C port (win32-qv) or +# - the multithreaded QP/C port (win32). +# +QP_PORT_DIR := $(QPC)/ports/win32-qv +#QP_PORT_DIR := $(QPC)/ports/win32 +LIB_DIRS += -L$(QP_PORT_DIR)/$(CONF) +LIBS += -lqp -lws2_32 + +else + +# NOTE: +# For POSIX hosts (Linux, MacOS), you can choose: +# - the single-threaded QP/C port (win32-qv) or +# - the multithreaded QP/C port (win32). +# +QP_PORT_DIR := $(QPC)/ports/posix-qv +#QP_PORT_DIR := $(QPC)/ports/posix + +C_SRCS += \ + qep_hsm.c \ + qep_msm.c \ + qf_act.c \ + qf_actq.c \ + qf_defer.c \ + qf_dyn.c \ + qf_mem.c \ + qf_ps.c \ + qf_qact.c \ + qf_qeq.c \ + qf_qmact.c \ + qf_time.c \ + qf_port.c + +QS_SRCS := \ + qs.c \ + qs_64bit.c \ + qs_rx.c \ + qs_fp.c \ + qs_port.c + +LIBS += -lpthread + +endif + +#============================================================================ +# Typically you should not need to change anything below this line + +VPATH += $(QPC)/src/qf $(QP_PORT_DIR) +INCLUDES += -I$(QPC)/include -I$(QPC)/src -I$(QP_PORT_DIR) + +#----------------------------------------------------------------------------- +# GNU toolset: +# +# NOTE: +# GNU toolset (MinGW) is included in the QTools collection for Windows, see: +# http://sourceforge.net/projects/qpc/files/QTools/ +# It is assumed that %QTOOLS%\bin directory is added to the PATH +# +CC := gcc +CPP := g++ +LINK := gcc # for C programs +#LINK := g++ # for C++ programs + +#----------------------------------------------------------------------------- +# basic utilities (depends on the OS this Makefile runs on): +# +ifeq ($(OS),Windows_NT) + MKDIR := mkdir + RM := rm + TARGET_EXT := .exe +else ifeq ($(OSTYPE),cygwin) + MKDIR := mkdir -p + RM := rm -f + TARGET_EXT := .exe +else + MKDIR := mkdir -p + RM := rm -f + TARGET_EXT := +endif + +#----------------------------------------------------------------------------- +# build configurations... + +ifeq (rel, $(CONF)) # Release configuration .................................. + +BIN_DIR := build_rel +# gcc options: +CFLAGS = -c -O3 -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ + $(INCLUDES) $(DEFINES) -DNDEBUG + +CPPFLAGS = -c -O3 -fno-pie -std=c++11 -pedantic -Wall -Wextra \ + -fno-rtti -fno-exceptions \ + $(INCLUDES) $(DEFINES) -DNDEBUG + +else ifeq (spy, $(CONF)) # Spy configuration ................................ + +BIN_DIR := build_spy + +C_SRCS += $(QS_SRCS) +VPATH += $(QPC)/src/qs + +# gcc options: +CFLAGS = -c -g -O -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ + $(INCLUDES) $(DEFINES) -DQ_SPY + +CPPFLAGS = -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \ + -fno-rtti -fno-exceptions \ + $(INCLUDES) $(DEFINES) -DQ_SPY + +else # default Debug configuration ......................................... + +BIN_DIR := build + +# gcc options: +CFLAGS = -c -g -O -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ + $(INCLUDES) $(DEFINES) + +CPPFLAGS = -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \ + -fno-rtti -fno-exceptions \ + $(INCLUDES) $(DEFINES) + +endif # ..................................................................... + +ifndef GCC_OLD + LINKFLAGS := -no-pie +endif + +#----------------------------------------------------------------------------- +C_OBJS := $(patsubst %.c,%.o, $(C_SRCS)) +CPP_OBJS := $(patsubst %.cpp,%.o, $(CPP_SRCS)) + +TARGET_EXE := $(BIN_DIR)/$(PROJECT)$(TARGET_EXT) +C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) +C_DEPS_EXT := $(patsubst %.o,%.d, $(C_OBJS_EXT)) +CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) +CPP_DEPS_EXT := $(patsubst %.o,%.d, $(CPP_OBJS_EXT)) + +# create $(BIN_DIR) if it does not exist +ifeq ("$(wildcard $(BIN_DIR))","") +$(shell $(MKDIR) $(BIN_DIR)) +endif + +#----------------------------------------------------------------------------- +# rules +# + +all: $(TARGET_EXE) + +$(TARGET_EXE) : $(C_OBJS_EXT) $(CPP_OBJS_EXT) + $(CC) $(CFLAGS) $(QPC)/include/qstamp.c -o $(BIN_DIR)/qstamp.o + $(LINK) $(LINKFLAGS) $(LIB_DIRS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) + +$(BIN_DIR)/%.d : %.c + $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ + +$(BIN_DIR)/%.d : %.cpp + $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ + +$(BIN_DIR)/%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +$(BIN_DIR)/%.o : %.cpp + $(CPP) $(CPPFLAGS) $< -o $@ + +.PHONY : clean show + +# include dependency files only if our goal depends on their existence +ifneq ($(MAKECMDGOALS),clean) + ifneq ($(MAKECMDGOALS),show) +-include $(C_DEPS_EXT) $(CPP_DEPS_EXT) + endif +endif + +.PHONY : clean show + +clean : + -$(RM) $(BIN_DIR)/*.o \ + $(BIN_DIR)/*.d \ + $(TARGET_EXE) + +show : + @echo PROJECT = $(PROJECT) + @echo TARGET_EXE = $(TARGET_EXE) + @echo VPATH = $(VPATH) + @echo C_SRCS = $(C_SRCS) + @echo CPP_SRCS = $(CPP_SRCS) + @echo C_DEPS_EXT = $(C_DEPS_EXT) + @echo C_OBJS_EXT = $(C_OBJS_EXT) + @echo C_DEPS_EXT = $(C_DEPS_EXT) + @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) + @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) + @echo LIB_DIRS = $(LIB_DIRS) + @echo LIBS = $(LIBS) + @echo DEFINES = $(DEFINES) + diff --git a/examples/workstation/calc2/bsp.c b/examples/workstation/calc2/bsp.c new file mode 100644 index 00000000..c0beb6ee --- /dev/null +++ b/examples/workstation/calc2/bsp.c @@ -0,0 +1,120 @@ +/***************************************************************************** +* Product: Board Support Package (BSP) for the Calculator example +* Last updated for version 6.9.0 +* Last updated on 2020-06-24 +* +* Q u a n t u m L e a P s +* ------------------------ +* Modern Embedded Software +* +* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* +* This program is open source software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Alternatively, this program may be distributed and modified under the +* terms of Quantum Leaps commercial licenses, which expressly supersede +* the GNU General Public License and are specifically designed for +* licensees interested in retaining the proprietary status of their code. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Contact information: +* +* +*****************************************************************************/ +#include "qpc.h" +#include "bsp.h" + +#include "safe_std.h" /* portable "safe" / facilities */ +#include /* for exit() */ + +#define DISP_WIDTH 15 + +/* helper macros to "stringify" values */ +#define VAL(x) #x +#define STRINGIFY(x) VAL(x) + +static char l_display[DISP_WIDTH + 1]; /* the calculator display */ +static int l_len; /* number of displayed characters */ + +/*..........................................................................*/ +void BSP_clear(void) { + memset(l_display, ' ', DISP_WIDTH - 1); + l_display[DISP_WIDTH - 1] = '0'; + l_display[DISP_WIDTH] = '\0'; + l_len = 0; +} +/*..........................................................................*/ +void BSP_insert(int keyId) { + if (l_len == 0) { + l_display[DISP_WIDTH - 1] = (char)keyId; + ++l_len; + } + else if (l_len < (DISP_WIDTH - 1)) { + MEMMOVE_S(&l_display[0], DISP_WIDTH, &l_display[1], DISP_WIDTH - 1); + l_display[DISP_WIDTH - 1] = (char)keyId; + ++l_len; + } +} +/*..........................................................................*/ +void BSP_display(double value) { + SNPRINTF_S(l_display, Q_DIM(l_display), + "%" STRINGIFY(DISP_WIDTH) ".6g", value); +} +/*..........................................................................*/ +void BSP_display_error(char const *err) { + STRNCPY_S(l_display, DISP_WIDTH, err); +} +/*..........................................................................*/ +void BSP_negate(void) { + BSP_clear(); + l_display[DISP_WIDTH - 2] = '-'; +} +/*..........................................................................*/ +void BSP_show_display(void) { + PRINTF_S("\n[%" STRINGIFY(DISP_WIDTH) "s] ", l_display); +} +/*..........................................................................*/ +void BSP_exit(void) { + PRINTF_S("\n%s\n", "Bye! Bye!"); + fflush(stdout); + QF_onCleanup(); + exit(0); +} +/*..........................................................................*/ +double BSP_get_value(void) { + return strtod(l_display, (char **)0); +} +/*..........................................................................*/ +void BSP_message(char const *msg) { + PRINTF_S("%s", msg); +} + +/*..........................................................................*/ +void QF_onStartup(void) { + QF_consoleSetup(); +} +/*..........................................................................*/ +void QF_onCleanup(void) { + QF_consoleCleanup(); +} +/*..........................................................................*/ +void QF_onClockTick(void) { +} + +/*..........................................................................*/ +/* this function is used by the QP embedded systems-friendly assertions */ +Q_NORETURN Q_onAssert(char const * const module, int_t const loc) { + FPRINTF_S(stderr, "Assertion failed in %s:%d", module, loc); + QF_onCleanup(); + exit(-1); +} diff --git a/examples/workstation/calc2/bsp.h b/examples/workstation/calc2/bsp.h new file mode 100644 index 00000000..ef2345da --- /dev/null +++ b/examples/workstation/calc2/bsp.h @@ -0,0 +1,48 @@ +/***************************************************************************** +* Product: Board Support Package (BSP) for the Calculator example +* Last updated for version 6.5.0 +* Last updated on 2019-03-20 +* +* Q u a n t u m L e a P s +* ------------------------ +* Modern Embedded Software +* +* Copyright (C) 2005-2019 Quantum Leaps, LLC. All rights reserved. +* +* This program is open source software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Alternatively, this program may be distributed and modified under the +* terms of Quantum Leaps commercial licenses, which expressly supersede +* the GNU General Public License and are specifically designed for +* licensees interested in retaining the proprietary status of their code. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Contact information: +* +* +*****************************************************************************/ +#ifndef BSP_H +#define BSP_H + +void BSP_clear(void); +void BSP_negate(void); +void BSP_insert(int keyId); +double BSP_get_value(void); +void BSP_display(double value); +void BSP_display_error(char const *err); +void BSP_exit(void); + +void BSP_show_display(void); +void BSP_message(char const *msg); + +#endif /* BSP_H */ diff --git a/examples/workstation/calc2/calc.sln b/examples/workstation/calc2/calc.sln new file mode 100644 index 00000000..829af870 --- /dev/null +++ b/examples/workstation/calc2/calc.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2013 for Windows Desktop +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "calc", "calc.vcxproj", "{8CC465F7-872E-4D03-B93C-1B64858B4E11}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + QSpy|Win32 = QSpy|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8CC465F7-872E-4D03-B93C-1B64858B4E11}.Debug|Win32.ActiveCfg = Debug|Win32 + {8CC465F7-872E-4D03-B93C-1B64858B4E11}.Debug|Win32.Build.0 = Debug|Win32 + {8CC465F7-872E-4D03-B93C-1B64858B4E11}.Release|Win32.ActiveCfg = Release|Win32 + {8CC465F7-872E-4D03-B93C-1B64858B4E11}.Release|Win32.Build.0 = Release|Win32 + {8CC465F7-872E-4D03-B93C-1B64858B4E11}.QSpy|Win32.ActiveCfg = QSpy|Win32 + {8CC465F7-872E-4D03-B93C-1B64858B4E11}.QSpy|Win32.Build.0 = QSpy|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/examples/workstation/calc2/calc.vcxproj b/examples/workstation/calc2/calc.vcxproj new file mode 100644 index 00000000..2e9c9dd7 --- /dev/null +++ b/examples/workstation/calc2/calc.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + QSpy + Win32 + + + + {8CC465F7-872E-4D03-B93C-1B64858B4E11} + calc + Win32Proj + 10.0 + + + + Application + NotSet + v142 + + + Application + NotSet + true + v142 + + + Application + NotSet + v142 + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + + Disabled + .;../../../include;../../../ports/win32-qv;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + NotUsing + Level4 + ProgramDatabase + 4127 + Default + + + qp.lib;%(AdditionalDependencies) + ../../../ports/win32-qv/$(Configuration);%(AdditionalLibraryDirectories) + true + Console + MachineX86 + + + cmd /c "del $(OutDir)qstamp.obj" + + + + + MaxSpeed + true + .;../../../include;../../../ports/win32-qv;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_CONSOLE;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + NotUsing + Level4 + ProgramDatabase + 4127 + + + qp.lib;%(AdditionalDependencies) + ../../../ports/win32-qv/$(Configuration);%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + cmd /c "del $(OutDir)qstamp.obj" + + + + + Disabled + .;../../../include;../../../ports/win32-qv;$(QTOOLS)/qspy/include;%(AdditionalIncludeDirectories) + Q_SPY;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + NotUsing + Level4 + ProgramDatabase + 4127 + + + qp.lib;ws2_32.lib;%(AdditionalDependencies) + ../../../ports/win32-qv/$(Configuration);%(AdditionalLibraryDirectories) + true + Console + MachineX86 + + + cmd /c "del $(OutDir)qstamp.obj" + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/workstation/calc2/calc.vcxproj.filters b/examples/workstation/calc2/calc.vcxproj.filters new file mode 100644 index 00000000..7932792d --- /dev/null +++ b/examples/workstation/calc2/calc.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/workstation/calc2/calc2.c b/examples/workstation/calc2/calc2.c new file mode 100644 index 00000000..9094360e --- /dev/null +++ b/examples/workstation/calc2/calc2.c @@ -0,0 +1,681 @@ +/*.$file${.::calc2.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/* +* Model: calc2.qm +* File: ${.::calc2.c} +* +* This code has been generated by QM 5.1.0 . +* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +* +* This program is open source software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published +* by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* for more details. +*/ +/*.$endhead${.::calc2.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +#include "qpc.h" /* QP/C */ +#include "bsp.h" /* board support package */ +#include "calc2.h" /* application */ + +Q_DEFINE_THIS_FILE + +#define KEY_NULL '\0' +#define KEY_PLUS '+' +#define KEY_MINUS '-' +#define KEY_MULT '*' +#define KEY_DIVIDE '/' + +/*.$declare${SMs::Calc} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*.${SMs::Calc} ............................................................*/ +typedef struct Calc { +/* protected: */ + QHsm super; + +/* public: */ + +/* private: */ + double op1; + double op2; + uint8_t oper1; + uint8_t oper2; +} Calc; + +/* private: */ + +/* guard function to evaluate the current expression +* taking into account the precedence of operands. +* return: true if evaluation successfull +* false when error encountered +*/ +static bool Calc_eval(Calc * const me, double op, uint8_t oper); +extern Calc Calc_inst; + +/* protected: */ +static QState Calc_initial(Calc * const me, void const * const par); +static QState Calc_on(Calc * const me, QEvt const * const e); + +/* Error state after evaluation of an expression. +This state can be exited only throgh the inherited C (Clear) event. +*/ +static QState Calc_error(Calc * const me, QEvt const * const e); +static QState Calc_ready(Calc * const me, QEvt const * const e); +static QState Calc_result(Calc * const me, QEvt const * const e); +static QState Calc_begin(Calc * const me, QEvt const * const e); +static QState Calc_operand(Calc * const me, QEvt const * const e); +static QState Calc_zero1(Calc * const me, QEvt const * const e); +static QState Calc_int1(Calc * const me, QEvt const * const e); +static QState Calc_frac1(Calc * const me, QEvt const * const e); +static QState Calc_negated1(Calc * const me, QEvt const * const e); +static QState Calc_opEntered(Calc * const me, QEvt const * const e); +static QState Calc_final(Calc * const me, QEvt const * const e); +/*.$enddecl${SMs::Calc} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + +/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*. Check for the minimum required QP version */ +#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) +#error qpc version 6.8.0 or higher required +#endif +/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*.$define${SMs::the_calc} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*.${SMs::the_calc} ........................................................*/ +QHsm * const the_calc = &Calc_inst.super; +/*.$enddef${SMs::the_calc} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*.$define${SMs::Calc_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*.${SMs::Calc_ctor} .......................................................*/ +void Calc_ctor(void) { + Calc *me = &Calc_inst; + QHsm_ctor(&me->super, Q_STATE_CAST(&Calc_initial)); +} +/*.$enddef${SMs::Calc_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*.$define${SMs::Calc} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*.${SMs::Calc} ............................................................*/ +Calc Calc_inst; + +/* guard function to evaluate the current expression +* taking into account the precedence of operands. +* return: true if evaluation successfull +* false when error encountered +*/ +/*.${SMs::Calc::eval} ......................................................*/ +static bool Calc_eval(Calc * const me, double op, uint8_t oper) { + double result; + if (me->oper1 == KEY_NULL) { /* no op1 yet */ + me->op1 = op; + me->oper1 = oper; + result = me->op1; + } + else if ((oper == KEY_NULL) || (oper == KEY_PLUS) || (oper == KEY_MINUS)) { + switch (me->oper2) { + case KEY_MULT: { + me->op2 *= op; + break; + } + case KEY_DIVIDE: { + if ((-1e-30 < op) && (op < 1e-30)) { + BSP_display_error(" Error 0 "); /* divide by zero */ + return false; + } + me->op2 /= op; + break; + } + default: { /* no op2 yet */ + me->op2 = op; + me->oper2 = oper; + break; + } + } + switch (me->oper1) { + case KEY_PLUS: { + me->op1 += me->op2; + break; + } + case KEY_MINUS: { + me->op1 -= me->op2; + break; + } + case KEY_MULT: { + me->op1 *= me->op2; + break; + } + case KEY_DIVIDE: { + if ((-1e-30 < me->op2) && (me->op2 < 1e-30)) { + BSP_display_error(" Error 0 "); /* divide by zero */ + return false; + } + me->op1 /= me->op2; + break; + } + default: { + Q_ERROR(); + break; + } + } + me->oper1 = oper; + me->oper2 = KEY_NULL; + result = me->op1; + } + else { /* (oper == KEY_MULT) || (oper == KEY_DIV) */ + switch (me->oper2) { + case KEY_MULT: { + me->op2 *= op; + break; + } + case KEY_DIVIDE: { + if ((-1e-30 < op) && (op < 1e-30)) { + BSP_display_error(" Error 0 "); /* divide by zero */ + return false; + } + me->op2 /= op; + break; + } + default: { /* oper2 not provided yet */ + me->op2 = op; + break; + } + } + me->oper2 = oper; + result = me->op2; + } + + if ((result < -99999999.0) || (99999999.0 < result)) { + BSP_display_error(" Error 1 "); /* out of range */ + return false; + } + if ((-0.0000001 < result) && (result < 0.0000001)) { + result = 0.0; + } + BSP_display(result); + + return true; +} + +/*.${SMs::Calc::SM} ........................................................*/ +static QState Calc_initial(Calc * const me, void const * const par) { + /*.${SMs::Calc::SM::initial} */ + (void)par; /* unused parameter */ + return Q_TRAN(&Calc_on); +} +/*.${SMs::Calc::SM::on} ....................................................*/ +static QState Calc_on(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on} */ + case Q_ENTRY_SIG: { + BSP_message("on-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on} */ + case Q_EXIT_SIG: { + BSP_message("on-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::initial} */ + case Q_INIT_SIG: { + BSP_message("on-INIT;"); + BSP_clear(); + status_ = Q_TRAN(&Calc_ready); + break; + } + /*.${SMs::Calc::SM::on::C} */ + case C_SIG: { + status_ = Q_TRAN(&Calc_on); + break; + } + /*.${SMs::Calc::SM::on::OFF} */ + case OFF_SIG: { + status_ = Q_TRAN(&Calc_final); + break; + } + default: { + status_ = Q_SUPER(&QHsm_top); + break; + } + } + return status_; +} + +/* Error state after evaluation of an expression. +This state can be exited only throgh the inherited C (Clear) event. +*/ +/*.${SMs::Calc::SM::on::error} .............................................*/ +static QState Calc_error(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::error} */ + case Q_ENTRY_SIG: { + BSP_message("error-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::error} */ + case Q_EXIT_SIG: { + BSP_message("error-EXIT;"); + status_ = Q_HANDLED(); + break; + } + default: { + status_ = Q_SUPER(&Calc_on); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::ready} .............................................*/ +static QState Calc_ready(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::ready} */ + case Q_ENTRY_SIG: { + BSP_message("ready-ENTRY;"); + me->oper1 = KEY_NULL; + me->oper2 = KEY_NULL; + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::ready} */ + case Q_EXIT_SIG: { + BSP_message("ready-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::ready::initial} */ + case Q_INIT_SIG: { + BSP_message("ready-INIT;"); + status_ = Q_TRAN(&Calc_begin); + break; + } + /*.${SMs::Calc::SM::on::ready::DIGIT_0} */ + case DIGIT_0_SIG: { + BSP_clear(); + status_ = Q_TRAN(&Calc_zero1); + break; + } + /*.${SMs::Calc::SM::on::ready::DIGIT_1_9} */ + case DIGIT_1_9_SIG: { + BSP_clear(); + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_TRAN(&Calc_int1); + break; + } + /*.${SMs::Calc::SM::on::ready::POINT} */ + case POINT_SIG: { + BSP_clear(); + BSP_insert((int)'0'); + BSP_insert((int)'.'); + status_ = Q_TRAN(&Calc_frac1); + break; + } + /*.${SMs::Calc::SM::on::ready::OPER} */ + case OPER_SIG: { + me->op1 = BSP_get_value(); + me->oper1 = Q_EVT_CAST(CalcEvt)->key_code; + status_ = Q_TRAN(&Calc_opEntered); + break; + } + default: { + status_ = Q_SUPER(&Calc_on); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::ready::result} .....................................*/ +static QState Calc_result(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::ready::result} */ + case Q_ENTRY_SIG: { + BSP_message("result-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::ready::result} */ + case Q_EXIT_SIG: { + BSP_message("result-EXIT;"); + status_ = Q_HANDLED(); + break; + } + default: { + status_ = Q_SUPER(&Calc_ready); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::ready::begin} ......................................*/ +static QState Calc_begin(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::ready::begin} */ + case Q_ENTRY_SIG: { + BSP_message("begin-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::ready::begin} */ + case Q_EXIT_SIG: { + BSP_message("begin-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::ready::begin::OPER} */ + case OPER_SIG: { + /*.${SMs::Calc::SM::on::ready::begin::OPER::[e->key=='-']} */ + if (Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS) { + status_ = Q_TRAN(&Calc_negated1); + } + /*.${SMs::Calc::SM::on::ready::begin::OPER::[else]} */ + else { + status_ = Q_HANDLED(); + } + break; + } + default: { + status_ = Q_SUPER(&Calc_ready); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::operand} ...........................................*/ +static QState Calc_operand(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::operand} */ + case Q_ENTRY_SIG: { + BSP_message("operand1-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand} */ + case Q_EXIT_SIG: { + BSP_message("operand1-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::CE} */ + case CE_SIG: { + BSP_clear(); + status_ = Q_TRAN(&Calc_ready); + break; + } + /*.${SMs::Calc::SM::on::operand::EQUALS} */ + case EQUALS_SIG: { + /*.${SMs::Calc::SM::on::operand::EQUALS::[Calc_eval(me,BSP_get_value(),KE~} */ + if (Calc_eval(me, BSP_get_value(), KEY_NULL)) { + status_ = Q_TRAN(&Calc_result); + } + /*.${SMs::Calc::SM::on::operand::EQUALS::[else]} */ + else { + status_ = Q_TRAN(&Calc_error); + } + break; + } + /*.${SMs::Calc::SM::on::operand::OPER} */ + case OPER_SIG: { + /*.${SMs::Calc::SM::on::operand::OPER::[Calc_eval(me,BSP_get_value(),Q_~} */ + if (Calc_eval(me, BSP_get_value(), Q_EVT_CAST(CalcEvt)->key_code)) { + status_ = Q_TRAN(&Calc_opEntered); + } + /*.${SMs::Calc::SM::on::operand::OPER::[else]} */ + else { + status_ = Q_TRAN(&Calc_error); + } + break; + } + default: { + status_ = Q_SUPER(&Calc_on); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::operand::zero1} ....................................*/ +static QState Calc_zero1(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::operand::zero1} */ + case Q_ENTRY_SIG: { + BSP_message("zero1-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::zero1} */ + case Q_EXIT_SIG: { + BSP_message("zero1-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::zero1::DIGIT_0} */ + case DIGIT_0_SIG: { + ; + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::zero1::DIGIT_1_9} */ + case DIGIT_1_9_SIG: { + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_TRAN(&Calc_int1); + break; + } + /*.${SMs::Calc::SM::on::operand::zero1::POINT} */ + case POINT_SIG: { + BSP_insert((int)'0'); + BSP_insert((int)'.'); + status_ = Q_TRAN(&Calc_frac1); + break; + } + default: { + status_ = Q_SUPER(&Calc_operand); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::operand::int1} .....................................*/ +static QState Calc_int1(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::operand::int1} */ + case Q_ENTRY_SIG: { + BSP_message("int1-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::int1} */ + case Q_EXIT_SIG: { + BSP_message("int1-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::int1::POINT} */ + case POINT_SIG: { + BSP_insert((int)'.'); + status_ = Q_TRAN(&Calc_frac1); + break; + } + /*.${SMs::Calc::SM::on::operand::int1::DIGIT_0, DIGIT_1_9} */ + case DIGIT_0_SIG: /* intentionally fall through */ + case DIGIT_1_9_SIG: { + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_HANDLED(); + break; + } + default: { + status_ = Q_SUPER(&Calc_operand); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::operand::frac1} ....................................*/ +static QState Calc_frac1(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::operand::frac1} */ + case Q_ENTRY_SIG: { + BSP_message("frac1-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::frac1} */ + case Q_EXIT_SIG: { + BSP_message("frac1-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::frac1::POINT} */ + case POINT_SIG: { + ; + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::frac1::DIGIT_0, DIGIT_1_9} */ + case DIGIT_0_SIG: /* intentionally fall through */ + case DIGIT_1_9_SIG: { + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_HANDLED(); + break; + } + default: { + status_ = Q_SUPER(&Calc_operand); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::operand::negated1} .................................*/ +static QState Calc_negated1(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::operand::negated1} */ + case Q_ENTRY_SIG: { + BSP_message("negated1-ENTRY;"); + BSP_negate(); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::negated1} */ + case Q_EXIT_SIG: { + BSP_message("negated1-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::operand::negated1::DIGIT_0} */ + case DIGIT_0_SIG: { + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_TRAN(&Calc_zero1); + break; + } + /*.${SMs::Calc::SM::on::operand::negated1::DIGIT_1_9} */ + case DIGIT_1_9_SIG: { + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_TRAN(&Calc_int1); + break; + } + /*.${SMs::Calc::SM::on::operand::negated1::POINT} */ + case POINT_SIG: { + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_TRAN(&Calc_frac1); + break; + } + /*.${SMs::Calc::SM::on::operand::negated1::OPER} */ + case OPER_SIG: { + /*.${SMs::Calc::SM::on::operand::negated1::OPER::[e->key=='-']} */ + if (Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS) { + ; + status_ = Q_HANDLED(); + } + /*.${SMs::Calc::SM::on::operand::negated1::OPER::[else]} */ + else { + status_ = Q_HANDLED(); + } + break; + } + default: { + status_ = Q_SUPER(&Calc_operand); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::on::opEntered} .........................................*/ +static QState Calc_opEntered(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::on::opEntered} */ + case Q_ENTRY_SIG: { + BSP_message("opEntered-ENTRY;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::opEntered} */ + case Q_EXIT_SIG: { + BSP_message("opEntered-EXIT;"); + status_ = Q_HANDLED(); + break; + } + /*.${SMs::Calc::SM::on::opEntered::DIGIT_0} */ + case DIGIT_0_SIG: { + BSP_clear(); + status_ = Q_TRAN(&Calc_zero1); + break; + } + /*.${SMs::Calc::SM::on::opEntered::DIGIT_1_9} */ + case DIGIT_1_9_SIG: { + BSP_clear(); + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + status_ = Q_TRAN(&Calc_int1); + break; + } + /*.${SMs::Calc::SM::on::opEntered::POINT} */ + case POINT_SIG: { + BSP_clear(); + BSP_insert((int)'0'); + BSP_insert((int)'.'); + status_ = Q_TRAN(&Calc_frac1); + break; + } + /*.${SMs::Calc::SM::on::opEntered::OPER} */ + case OPER_SIG: { + /*.${SMs::Calc::SM::on::opEntered::OPER::[e->key=='-']} */ + if (Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS) { + status_ = Q_TRAN(&Calc_negated1); + } + /*.${SMs::Calc::SM::on::opEntered::OPER::[else]} */ + else { + status_ = Q_HANDLED(); + } + break; + } + default: { + status_ = Q_SUPER(&Calc_on); + break; + } + } + return status_; +} +/*.${SMs::Calc::SM::final} .................................................*/ +static QState Calc_final(Calc * const me, QEvt const * const e) { + QState status_; + switch (e->sig) { + /*.${SMs::Calc::SM::final} */ + case Q_ENTRY_SIG: { + BSP_message("final-ENTRY;"); + BSP_exit(); + status_ = Q_HANDLED(); + break; + } + default: { + status_ = Q_SUPER(&QHsm_top); + break; + } + } + return status_; +} +/*.$enddef${SMs::Calc} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ diff --git a/examples/workstation/calc2/calc2.h b/examples/workstation/calc2/calc2.h new file mode 100644 index 00000000..5c17769d --- /dev/null +++ b/examples/workstation/calc2/calc2.h @@ -0,0 +1,50 @@ +/*.$file${.::calc2.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/* +* Model: calc2.qm +* File: ${.::calc2.h} +* +* This code has been generated by QM 5.1.0 . +* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +* +* This program is open source software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published +* by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* for more details. +*/ +/*.$endhead${.::calc2.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +#ifndef CALC2_H +#define CALC2_H + +enum CalcSignals { + C_SIG = Q_USER_SIG, + CE_SIG, + DIGIT_0_SIG, + DIGIT_1_9_SIG, + POINT_SIG, + OPER_SIG, + EQUALS_SIG, + OFF_SIG +}; + +/*.$declare${Events::CalcEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*.${Events::CalcEvt} ......................................................*/ +typedef struct { +/* protected: */ + QEvt super; + +/* public: */ + uint8_t key_code; +} CalcEvt; +/*.$enddecl${Events::CalcEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*.$declare${SMs::Calc_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*.${SMs::Calc_ctor} .......................................................*/ +void Calc_ctor(void); +/*.$enddecl${SMs::Calc_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + +extern QHsm * const the_calc; /* "opaque" pointer to calculator HSM */ + +#endif /* CALC2_H */ diff --git a/examples/workstation/calc2/calc2.qm b/examples/workstation/calc2/calc2.qm new file mode 100644 index 00000000..69de0275 --- /dev/null +++ b/examples/workstation/calc2/calc2.qm @@ -0,0 +1,582 @@ + + + Improved model of the Calculator described in Chapter 4 of PSiCC2. Improvements include: + +- placing the "negated1" state inside "operand1" superstate +- placing the "negated2" state inside "operand2" superstate +- adding handling of operator precedence '*','/' before '+','-' + + + + + + + + + + + + + + + Calculator state machine + + + The only inst of the Calc object (Singleton pattern). + + + + + + + + + + + + /* guard function to evaluate the current expression +* taking into account the precedence of operands. +* return: true if evaluation successfull +* false when error encountered +*/ + + + + + double result; +if (me->oper1 == KEY_NULL) { /* no op1 yet */ + me->op1 = op; + me->oper1 = oper; + result = me->op1; +} +else if ((oper == KEY_NULL) || (oper == KEY_PLUS) || (oper == KEY_MINUS)) { + switch (me->oper2) { + case KEY_MULT: { + me->op2 *= op; + break; + } + case KEY_DIVIDE: { + if ((-1e-30 < op) && (op < 1e-30)) { + BSP_display_error(" Error 0 "); /* divide by zero */ + return false; + } + me->op2 /= op; + break; + } + default: { /* no op2 yet */ + me->op2 = op; + me->oper2 = oper; + break; + } + } + switch (me->oper1) { + case KEY_PLUS: { + me->op1 += me->op2; + break; + } + case KEY_MINUS: { + me->op1 -= me->op2; + break; + } + case KEY_MULT: { + me->op1 *= me->op2; + break; + } + case KEY_DIVIDE: { + if ((-1e-30 < me->op2) && (me->op2 < 1e-30)) { + BSP_display_error(" Error 0 "); /* divide by zero */ + return false; + } + me->op1 /= me->op2; + break; + } + default: { + Q_ERROR(); + break; + } + } + me->oper1 = oper; + me->oper2 = KEY_NULL; + result = me->op1; +} +else { /* (oper == KEY_MULT) || (oper == KEY_DIV) */ + switch (me->oper2) { + case KEY_MULT: { + me->op2 *= op; + break; + } + case KEY_DIVIDE: { + if ((-1e-30 < op) && (op < 1e-30)) { + BSP_display_error(" Error 0 "); /* divide by zero */ + return false; + } + me->op2 /= op; + break; + } + default: { /* oper2 not provided yet */ + me->op2 = op; + break; + } + } + me->oper2 = oper; + result = me->op2; +} + +if ((result < -99999999.0) || (99999999.0 < result)) { + BSP_display_error(" Error 1 "); /* out of range */ + return false; +} +if ((-0.0000001 < result) && (result < 0.0000001)) { + result = 0.0; +} +BSP_display(result); + +return true; + + + + + + (void)par; /* unused parameter */ + + + + + + + BSP_message("on-ENTRY;"); + BSP_message("on-EXIT;"); + + + BSP_message("on-INIT;"); +BSP_clear(); + + + + + + + + + + + + + + + + + + + /* Error state after evaluation of an expression. +This state can be exited only throgh the inherited C (Clear) event. +*/ + BSP_message("error-ENTRY;"); + BSP_message("error-EXIT;"); + + + + + + + + BSP_message("ready-ENTRY;"); +me->oper1 = KEY_NULL; +me->oper2 = KEY_NULL; + BSP_message("ready-EXIT;"); + + + BSP_message("ready-INIT;"); + + + + + + + BSP_clear(); + + + + + + + BSP_clear(); +BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + BSP_clear(); +BSP_insert((int)'0'); +BSP_insert((int)'.'); + + + + + + + me->op1 = BSP_get_value(); +me->oper1 = Q_EVT_CAST(CalcEvt)->key_code; + + + + + + + BSP_message("result-ENTRY;"); + BSP_message("result-EXIT;"); + + + + + + + + BSP_message("begin-ENTRY;"); + BSP_message("begin-EXIT;"); + + + + + Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS + + + + + + + else + + + + + + + + + + + + + + + + + + + + + BSP_message("operand1-ENTRY;"); + BSP_message("operand1-EXIT;"); + + + BSP_clear(); + + + + + + + + + + + + + + + + Calc_eval(me, BSP_get_value(), KEY_NULL) + + + + + + + + + + + + + Calc_eval(me, BSP_get_value(), Q_EVT_CAST(CalcEvt)->key_code) + + + + + + + + + + + + + + + + + + BSP_message("zero1-ENTRY;"); + BSP_message("zero1-EXIT;"); + + + ; + + + + + + + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + BSP_insert((int)'0'); +BSP_insert((int)'.'); + + + + + + + + + + + + BSP_message("int1-ENTRY;"); + BSP_message("int1-EXIT;"); + + + BSP_insert((int)'.'); + + + + + + + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + + + + + + BSP_message("frac1-ENTRY;"); + BSP_message("frac1-EXIT;"); + + + ; + + + + + + + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + + + + + + BSP_message("negated1-ENTRY;"); +BSP_negate(); + BSP_message("negated1-EXIT;"); + + + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + + + else + + + + + + + Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS + ; + + + + + + + + + + + + + + + + + + + + + BSP_message("opEntered-ENTRY;"); + BSP_message("opEntered-EXIT;"); + + + BSP_clear(); + + + + + + + BSP_clear(); +BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); + + + + + + + BSP_clear(); +BSP_insert((int)'0'); +BSP_insert((int)'.'); + + + + + + + + + Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS + + + + + + + else + + + + + + + + + + + + + + + + + + + + + BSP_message("final-ENTRY;"); +BSP_exit(); + + + + + + + + + + Global opaque pointer to the Calc inst + = &Calc_inst.super; + + + + constructor + Calc *me = &Calc_inst; +QHsm_ctor(&me->super, Q_STATE_CAST(&Calc_initial)); + + + + + + + #ifndef CALC2_H +#define CALC2_H + +enum CalcSignals { + C_SIG = Q_USER_SIG, + CE_SIG, + DIGIT_0_SIG, + DIGIT_1_9_SIG, + POINT_SIG, + OPER_SIG, + EQUALS_SIG, + OFF_SIG +}; + +$declare${Events::CalcEvt} +$declare${SMs::Calc_ctor} + +extern QHsm * const the_calc; /* "opaque" pointer to calculator HSM */ + +#endif /* CALC2_H */ + + + + + #include "qpc.h" /* QP/C */ +#include "bsp.h" /* board support package */ +#include "calc2.h" /* application */ + +Q_DEFINE_THIS_FILE + +#define KEY_NULL '\0' +#define KEY_PLUS '+' +#define KEY_MINUS '-' +#define KEY_MULT '*' +#define KEY_DIVIDE '/' + +$declare${SMs::Calc} + +$define${SMs::the_calc} +$define${SMs::Calc_ctor} +$define${SMs::Calc} + + + diff --git a/examples/workstation/calc2/main.c b/examples/workstation/calc2/main.c new file mode 100644 index 00000000..01f10e25 --- /dev/null +++ b/examples/workstation/calc2/main.c @@ -0,0 +1,134 @@ +/***************************************************************************** +* Product: calc2 Example +* Last updated for version 6.9.3 +* Last updated on 2021-03-18 +* +* Q u a n t u m L e a P s +* ------------------------ +* Modern Embedded Software +* +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. +* +* This program is open source software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Alternatively, this program may be distributed and modified under the +* terms of Quantum Leaps commercial licenses, which expressly supersede +* the GNU General Public License and are specifically designed for +* licensees interested in retaining the proprietary status of their code. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Contact information: +* +* +*****************************************************************************/ +#include "qpc.h" +#include "bsp.h" +#include "calc2.h" + +#include "safe_std.h" /* portable "safe" / facilities */ + +Q_DEFINE_THIS_FILE + +/*..........................................................................*/ +int main() { + + QF_init(); + QF_onStartup(); + + PRINTF_S("Calculator example, QP version: %s\n" + "Press '0' .. '9' to enter a digit\n" + "Press '.' to enter the decimal point\n" + "Press '+' to add\n" + "Press '-' to subtract or negate a number\n" + "Press '*' to multiply\n" + "Press '/' to divide\n" + "Press '=' or to get the result\n" + "Press 'c' or 'C' to Cancel\n" + "Press 'e' or 'E' to Cancel Entry\n" + "Press to quit.\n\n", + QP_VERSION_STR); + + Calc_ctor(); /* explicitly instantiate the calculator object */ + QHSM_INIT(the_calc, (void *)0, 0U); /* trigger initial transition */ + + for (;;) { /* event loop */ + CalcEvt e; /* Calculator event */ + + BSP_show_display(); /* show the display */ + + PRINTF_S("%s"," : "); + fflush(stdout); + e.key_code = (uint8_t)QF_consoleWaitForKey(); + PRINTF_S("%c ", (e.key_code >= ' ') ? e.key_code : 'X'); + + switch (e.key_code) { + case 'c': /* intentionally fall through */ + case 'C': { + e.super.sig = C_SIG; + break; + } + case 'e': /* intentionally fall through */ + case 'E': { + e.super.sig = CE_SIG; + break; + } + case '0': { + e.super.sig = DIGIT_0_SIG; + break; + } + case '1': /* intentionally fall through */ + case '2': /* intentionally fall through */ + case '3': /* intentionally fall through */ + case '4': /* intentionally fall through */ + case '5': /* intentionally fall through */ + case '6': /* intentionally fall through */ + case '7': /* intentionally fall through */ + case '8': /* intentionally fall through */ + case '9': { + e.super.sig = DIGIT_1_9_SIG; + break; + } + case '.': { + e.super.sig = POINT_SIG; + break; + } + case '+': /* intentionally fall through */ + case '-': /* intentionally fall through */ + case '*': /* intentionally fall through */ + case '/': { + e.super.sig = OPER_SIG; + break; + } + case '=': /* intentionally fall through */ + case '\r': { /* Enter key */ + e.super.sig = EQUALS_SIG; + break; + } + case '\33': { /* ESC key */ + e.super.sig = OFF_SIG; + break; + } + default: { + e.super.sig = 0; /* invalid event */ + break; + } + } + + if (e.super.sig != 0) { /* valid event generated? */ + QHSM_DISPATCH(the_calc, &e.super, 0U); /* dispatch event */ + } + } + + QF_onCleanup(); + return 0; +} diff --git a/examples/workstation/dpp-comp/bsp.c b/examples/workstation/dpp-comp/bsp.c index b7d7a7ac..afa503aa 100644 --- a/examples/workstation/dpp-comp/bsp.c +++ b/examples/workstation/dpp-comp/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example (console) -* Last Updated for Version: 6.9.1 -* Date of the Last Update: 2020-09-10 +* Last Updated for Version: 6.9.3 +* Date of the Last Update: 2021-03-03 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -47,7 +47,9 @@ static uint32_t l_rnd; /* random seed */ enum { PHILO_STAT = QS_USER }; - static uint8_t const l_clock_tick = 0U; + + /* QSpy source IDs */ + static QSpyId const l_clock_tick = { 0U }; #endif /*..........................................................................*/ diff --git a/examples/workstation/dpp/bsp.c b/examples/workstation/dpp/bsp.c index 69c9cf61..dfc24d57 100644 --- a/examples/workstation/dpp/bsp.c +++ b/examples/workstation/dpp/bsp.c @@ -1,13 +1,13 @@ /***************************************************************************** * Product: DPP example (console) -* Last Updated for Version: 6.9.1 -* Date of the Last Update: 2020-09-10 +* Last Updated for Version: 6.9.3 +* Date of the Last Update: 2021-03-02 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -47,7 +47,9 @@ static uint32_t l_rnd; /* random seed */ enum { PHILO_STAT = QS_USER }; - static uint8_t const l_clock_tick = 0U; + + /* QSpy source IDs */ + static QSpyId const l_clock_tick = { QS_AP_ID }; #endif /*..........................................................................*/ diff --git a/examples/workstation/dpp/dpp.qm b/examples/workstation/dpp/dpp.qm index 2bf06502..21af7004 100644 --- a/examples/workstation/dpp/dpp.qm +++ b/examples/workstation/dpp/dpp.qm @@ -150,7 +150,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U); TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); @@ -254,7 +254,7 @@ for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */ me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -277,7 +277,7 @@ me->fork[m] = USED; me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; -QF_PUBLISH(&pe->super, me); +QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); @@ -319,7 +319,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -330,7 +330,7 @@ if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } diff --git a/examples/workstation/dpp/philo.c b/examples/workstation/dpp/philo.c index 41bf18bd..8f306cd1 100644 --- a/examples/workstation/dpp/philo.c +++ b/examples/workstation/dpp/philo.c @@ -211,7 +211,7 @@ static QState Philo_eating(Philo * const me, QEvt const * const e) { case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); status_ = Q_HANDLED(); break; } diff --git a/examples/workstation/dpp/table.c b/examples/workstation/dpp/table.c index 8053c59c..9998bdb9 100644 --- a/examples/workstation/dpp/table.c +++ b/examples/workstation/dpp/table.c @@ -155,7 +155,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; te = Q_NEW(TableEvt, EAT_SIG); te->philoNum = n; - QF_PUBLISH(&te->super, me); + QF_PUBLISH(&te->super, &me->super); me->isHungry[n] = 0U; BSP_displayPhilStat(n, "eating "); } @@ -180,7 +180,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->fork[n] = USED; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = n; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(n, "eating "); status_ = Q_HANDLED(); } @@ -215,7 +215,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } m = LEFT(n); /* check the left neighbor */ @@ -226,7 +226,7 @@ static QState Table_serving(Table * const me, QEvt const * const e) { me->isHungry[m] = 0U; pe = Q_NEW(TableEvt, EAT_SIG); pe->philoNum = m; - QF_PUBLISH(&pe->super, me); + QF_PUBLISH(&pe->super, &me->super); BSP_displayPhilStat(m, "eating "); } status_ = Q_HANDLED(); diff --git a/examples/workstation/qhsmtst/SM_of_QHsmTst.png b/examples/workstation/qhsmtst/SM_of_QHsmTst.png new file mode 100644 index 00000000..fb10cefc Binary files /dev/null and b/examples/workstation/qhsmtst/SM_of_QHsmTst.png differ diff --git a/include/qep.h b/include/qep.h index 80ca18b2..a38a78f6 100644 --- a/include/qep.h +++ b/include/qep.h @@ -4,14 +4,14 @@ * @ingroup qep * @cond ****************************************************************************** -* Last updated for version 6.9.2 -* Last updated on 2020-12-16 +* Last updated for version 6.9.3 +* Last updated on 2021-02-26 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -45,16 +45,16 @@ * major version number, Y is a 1-digit minor version number, and Z is * a 1-digit release number. */ -#define QP_VERSION 692U +#define QP_VERSION 693U /*! The current QP version number string of the form XX.Y.Z, where XX is * a 2-digit major version number, Y is a 1-digit minor version number, * and Z is a 1-digit release number. */ -#define QP_VERSION_STR "6.9.2" +#define QP_VERSION_STR "6.9.3" -/*! Encrypted current QP release (6.9.2) and date (2021-01-18) */ -#define QP_RELEASE 0x82C286EBU +/*! Encrypted current QP release (6.9.3) and date (2021-04-12) */ +#define QP_RELEASE 0x8295AA8AU /****************************************************************************/ @@ -315,6 +315,8 @@ struct QHsmVtable { * @param[in,out] me_ pointer (see @ref oop) * @param[in] e_ constant pointer the ::QEvt or a class derived from * ::QEvt (see @ref oop) + * @param[in] qs_id_ QS local filter ID + * * @note Must be called only ONCE after the SM "constructor". * * @usage @@ -327,7 +329,7 @@ struct QHsmVtable { (*(me_)->vptr->init)((me_), (par_), (qs_id_)); \ } while (false) - /*! Implementation of the top-most initial transition in ::QHsm subclass */ + /*! Implementation of the top-most initial tran. in ::QHsm subclass */ void QHsm_init_(QHsm * const me, void const * const e, uint_fast8_t const qs_id); #else @@ -337,7 +339,7 @@ struct QHsmVtable { (*(me_)->vptr->init)((me_), (par_)); \ } while (false) - /*! Implementation of the top-most initial transition in ::QHsm subclass */ + /*! Implementation of the top-most initial tran. in ::QHsm subclass */ void QHsm_init_(QHsm * const me, void const * const e); #endif /* Q_SPY */ @@ -352,8 +354,8 @@ struct QHsmVtable { * Processes one event at a time in Run-to-Completion fashion. * * @param[in,out] me_ pointer (see @ref oop) - * @param[in] e_ constant pointer the ::QEvt or a structure derived from - * ::QEvt (see @ref oop) + * @param[in] e_ constant pointer the ::QEvt or a structure + * derived from ::QEvt (see @ref oop) * @note Must be called after the "constructor" and after QHSM_INIT(). */ #define QHSM_DISPATCH(me_, e_, qs_id_) \ diff --git a/include/qf.h b/include/qf.h index ee17baea..f12b0496 100644 --- a/include/qf.h +++ b/include/qf.h @@ -4,14 +4,14 @@ * @ingroup qf * @cond ****************************************************************************** -* Last updated for version 6.8.2 -* Last updated on 2020-07-14 +* Last updated for version 6.9.3 +* Last updated on 2021-02-26 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2019 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -604,7 +604,8 @@ void QF_onCleanup(void); #ifdef Q_SPY /*! Publish event to the framework. */ - void QF_publish_(QEvt const * const e, void const * const sender); + void QF_publish_(QEvt const * const e, + void const * const sender, uint_fast8_t const qs_id); /*! Invoke the event publishing facility QF_publish_(). */ /** @@ -615,12 +616,11 @@ void QF_onCleanup(void); * * @param[in] e_ pointer to the posted event * @param[in] sender_ pointer to the sender object. This argument is - * actually only used when QS software tracing is enabled - * (macro #Q_SPY is defined). When QS software tracing is - * disabled, the macro calls QF_publish_() without the - * @p sender_ parameter, so the overhead of passing this - * extra argument is entirely avoided. - * + * actually only used when QS software tracing is enabled + * (macro #Q_SPY is defined). When QS software tracing is + * disabled, the macro calls QF_publish_() without the + * @p sender_ parameter, so the overhead of passing this + * extra argument is entirely avoided. * @note * the pointer to the sender object is not necessarily a pointer * to an active object. In fact, if QF_PUBLISH() is called from an @@ -630,7 +630,8 @@ void QF_onCleanup(void); * @sa QF_publish_(). */ #define QF_PUBLISH(e_, sender_) \ - (QF_publish_((e_), (void const *)(sender_))) + (QF_publish_((e_), (void const *)(sender_), (sender_)->prio)) + #else void QF_publish_(QEvt const * const e); diff --git a/include/qs.h b/include/qs.h index 92170abe..aea8654f 100644 --- a/include/qs.h +++ b/include/qs.h @@ -240,6 +240,9 @@ enum QSpyIdGroups { QS_AP_IDS = (0x80 + (enum_t)QS_AP_ID), /*!< Application-specific IDs */ }; +/*! QSpy ID type for applying local filtering */ +typedef struct { uint8_t prio; } QSpyId; + #ifndef QS_TIME_SIZE /*! The size [bytes] of the QS time stamp. Valid values: 1U, 2U, or 4U; diff --git a/ports/README.url b/ports/README.url index 8b7d7869..88569d16 100644 --- a/ports/README.url +++ b/ports/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/ports.html +URL=https://www.state-machine.com/qpc/ports.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/arm-cm/README.url b/ports/arm-cm/README.url index 2ef304da..b49b8922 100644 --- a/ports/arm-cm/README.url +++ b/ports/arm-cm/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=https://state-machine.com/qpc/arm-cm.html +URL=https://www.state-machine.com/qpc/arm-cm.html IconFile=https://state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/arm7-9/README.url b/ports/arm7-9/README.url index 7558e1e0..754e68ee 100644 --- a/ports/arm7-9/README.url +++ b/ports/arm7-9/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/arm7-9.html +URL=https://www.state-machine.com/qpc/arm7-9.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/embos/README.url b/ports/embos/README.url index 3fa0caa5..1a20bf36 100644 --- a/ports/embos/README.url +++ b/ports/embos/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=https://state-machine.com/qpc/embos.html +URL=https://www.state-machine.com/qpc/embos.html IconFile=https://state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/embos/qf_port.c b/ports/embos/qf_port.c index 8be4f8fa..3042df31 100644 --- a/ports/embos/qf_port.c +++ b/ports/embos/qf_port.c @@ -4,8 +4,8 @@ * @ingroup ports * @cond ****************************************************************************** -* Last updated for version 6.9.2a -* Last updated on 2021-01-26 +* Last updated for version 6.9.3 +* Last updated on 2021-04-09 * * Q u a n t u m L e a P s * ------------------------ @@ -94,7 +94,7 @@ static void thread_function(void *pVoid) { /* embOS signature */ #ifdef __TARGET_FPU_VFP /* does the task use the FPU? see NOTE1 */ - if ((act->osObject & QF_TASK_USES_FPU) != 0U) { + if ((act->osObject & TASK_USES_FPU) != 0U) { OS_ExtendTaskContext_VFP(); } #endif /* __TARGET_FPU_VFP */ @@ -112,8 +112,6 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, void * const stkSto, uint_fast16_t const stkSize, void const * const par) { - char task_name[4]; /* task name to be passed to OS_CreateTaskEx() */ - /* create the embOS message box for the AO */ OS_CreateMB(&me->eQueue, (OS_U16)sizeof(QEvt *), @@ -125,17 +123,13 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, QHSM_INIT(&me->super, par, me->prio); /* the top-most initial tran. */ QS_FLUSH(); /* flush the trace buffer to the host */ - /* prepare the unique task name of the form "Axx", - * where xx is a 2-digit QP priority of the Active Object - */ - task_name[0] = 'A'; - task_name[1] = '0' + (prio / 10U); - task_name[2] = '0' + (prio % 10U); - task_name[3] = '\0'; /* zero-terminate */ - /* create an embOS task for the AO */ OS_CreateTaskEx(&me->thread, - task_name, /* the unique task name */ +#if (OS_TRACKNAME != 0) + me->thread.Name, /* the configured task name */ +#elif + "AO", /* a generic AO task name */ +#endif (OS_PRIO)prio, /* embOS uses the same numbering as QP */ &thread_function, (void OS_STACKPTR *)stkSto, @@ -145,8 +139,20 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, } /*..........................................................................*/ void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) { - (void)attr2; /* unused parameter */ - me->osObject = attr1; + switch (attr1) { + case TASK_NAME_ATTR: +#if (OS_TRACKNAME != 0) + Q_ASSERT_ID(300, me->thread.Name == (char_t *)0); + me->thread.Name = (char_t const *)attr2; +#endif + break; + case TASK_USES_FPU: + me->osObject = attr1; + break; + /* ... */ + default: + break; + } } /*..........................................................................*/ #ifndef Q_SPY diff --git a/ports/embos/qf_port.h b/ports/embos/qf_port.h index 9acb458f..ccc0d1b3 100644 --- a/ports/embos/qf_port.h +++ b/ports/embos/qf_port.h @@ -4,8 +4,8 @@ * @ingroup ports * @cond ****************************************************************************** -* Last Updated for Version: 6.9.1 / embOS v4.34.1 -* Last updated on 2020-09-08 +* Last Updated for Version: 6.9.3 / embOS v4.34.1 +* Last updated on 2021-04-09 * * Q u a n t u m L e a P s * ------------------------ @@ -57,8 +57,11 @@ #define QF_CRIT_ENTRY(dummy) QF_INT_DISABLE() #define QF_CRIT_EXIT(dummy) QF_INT_ENABLE() -/* thread options... */ -#define QF_TASK_USES_FPU 1U +/* thread attributes... */ +enum EmbOS_TaskAttrs { + TASK_NAME_ATTR, + TASK_USES_FPU +}; #include "RTOS.h" /* embOS API */ #include "qep_port.h" /* QEP port */ diff --git a/ports/lint-plus/au-misra3-amd1.lnt b/ports/lint-plus/au-misra3-amd1.lnt index a703363d..f9b8801c 100644 --- a/ports/lint-plus/au-misra3-amd1.lnt +++ b/ports/lint-plus/au-misra3-amd1.lnt @@ -166,13 +166,13 @@ /**** Rule 21.15 (Req) ************/ - +e857 /* incompatible pointer arguments to memcpy/memmove/memcmp */ + +e857 /* incompatible pointer arguments to memcpy/memmove/memcmp */ +elib(857) -append(857,[MISRA 2012 Rule 21.15, required]) /**** Rule 21.16 (Req) ************/ - +e9098 /* pointer argument to memcmp does not point to a pointer type + +e9098 /* pointer argument to memcmp does not point to a pointer type or an essentially signed, unsigned, boolean, or enum type */ +elib(9098) -append(9098,[MISRA 2012 Rule 21.16, required]) diff --git a/ports/lint-plus/au-misra3.lnt b/ports/lint-plus/au-misra3.lnt index e20961fa..735be3fb 100644 --- a/ports/lint-plus/au-misra3.lnt +++ b/ports/lint-plus/au-misra3.lnt @@ -44,7 +44,7 @@ /**** Dir 2.1 (Req) ************/ - -std(c99) /* strict ISO C99 */ + -std(c99) /* strict ISO C99 */ /* Note: if you code to the C90 standard instead, you may want to comment out the above option and uncomment the following option. You will also want to do likewise for @@ -87,7 +87,7 @@ /**** Dir 4.5 (Adv) ************/ +fta /* enable typographical ambiguity checking */ - +e9046 /* typographical ambiguity */ + +e9046 /* typographical ambiguity */ +elib(9046) -append(9046,[MISRA 2012 Directive 4.5, advisory]) @@ -96,10 +96,9 @@ +e970 /* flag modifiers used outside of typedefs */ +elib(970) -append(970,[MISRA 2012 Directive 4.6, advisory]) - // For the duration, we are presuming MISRA does not want - // diagnostics for the bool type. - -esym(970,bool) - -esym(970,char) + -estring(970,bool) + -estring(970,_Bool) + -estring(970,char) /**** Dir 4.7 (Req) ************/ @@ -150,7 +149,7 @@ /* While MISRA has declared this rule to be "undecidable", Gimpel * Software provides the following options to assist: */ - -std(c99) /* strict ISO C99 */ + -std(c99) /* strict ISO C99 */ /* Note: if you code to the C90 standard instead, you may want to comment out the above option and uncomment the following option. You will also want to do likewise for @@ -162,7 +161,7 @@ /* While MISRA has declared this rule to be "undecidable", Gimpel * Software provides the following options to assist: */ - -std(c99) /* strict ISO C99 */ + -std(c99) /* strict ISO C99 */ /* Note: if you code to the C90 standard instead, you may want to comment out the above option and uncomment the following option. You will also want to do likewise for @@ -492,16 +491,16 @@ /**** Rule 2.3 (Adv) ************/ - +e751 /* local typedef not referenced */ + +e751 /* local typedef not referenced */ +elib(751) -append(751,[MISRA 2012 Rule 2.3, advisory]) - +e756 /* global not referenced */ + +e756 /* global not referenced */ +elib(756) -append(756,[MISRA 2012 Rule 2.3, advisory]) /**** Rule 2.4 (Adv) ************/ - +e753 /* local tag not referenced */ + +e753 /* local tag not referenced */ +elib(753) -append(753,[MISRA 2012 Rule 2.4, advisory]) +e9058 @@ -510,22 +509,22 @@ /**** Rule 2.5 (Adv) ************/ - +e750 /* local macro not referenced */ + +e750 /* local macro not referenced */ +elib(750) -append(750,[MISRA 2012 Rule 2.5, advisory]) - +e755 /* global macro not referenced */ + +e755 /* global macro not referenced */ +elib(755) -append(755,[MISRA 2012 Rule 2.5, advisory]) /**** Rule 2.6 (Adv) ************/ - +e563 /* label not referenced */ + +e563 /* label not referenced */ +elib(563) -append(563,[MISRA 2012 Rule 2.6, advisory]) /**** Rule 2.7 (Adv) ************/ - +e715 /* not referenced */ + +e715 /* not referenced */ +elib(715) -append(715,[MISRA 2012 Rule 2.7, advisory]) @@ -547,7 +546,7 @@ /**** Rule 3.2 (Req) ************/ - +e427 /* C++ comment ends in \\ */ + +e427 /* C++ comment ends in \\ */ +elib(427) -append(427,[MISRA 2012 Rule 3.2, required]) @@ -815,7 +814,7 @@ /**** Rule 8.10 (Req) ************/ - +e695 /* inline function without storage-class specifier */ + +e695 /* inline function without storage-class specifier */ +elib(695) -append(695,[MISRA 2012 Rule 8.10, required]) +estring(9056,extern) /* inline function defined with extern */ @@ -829,7 +828,7 @@ /**** Rule 8.12 (Req) ************/ - +e488 /* duplicate enumerator values */ + +e488 /* duplicate enumerator values */ +elib(488) -append(488,[MISRA 2012 Rule 8.12, required]) @@ -838,13 +837,13 @@ /* While MISRA has declared this rule to be "undecidable", Gimpel * Software provides the following options to assist: */ - +e818 /* pointer could be declared pointing to const */ + +e818 /* pointer could be declared pointing to const */ +elib(818) -append(818,[MISRA 2012 Rule 8.13, advisory]) - +e844 /* pointer could be declared pointing to const */ + +e844 /* pointer could be declared pointing to const */ +elib(844) -append(844,[MISRA 2012 Rule 8.13, advisory]) - +e954 /* pointer could be declared pointing to const */ + +e954 /* pointer could be declared pointing to const */ +elib(954) -append(954,[MISRA 2012 Rule 8.13, advisory]) @@ -900,7 +899,7 @@ /**** Rule 10.1 (Req) ************/ - +e48 /* bad type */ + +e48 /* bad type */ +elib(48) -append(48,[MISRA 2012 Rule 10.1, required]) +e9027 /* unpermitted operand */ @@ -1068,7 +1067,7 @@ /* While MISRA has declared this rule to be "undecidable", Gimpel * Software provides the following options to assist: */ - +e564 /* variable depends on order of evaluation */ + +e564 /* variable depends on order of evaluation */ +elib(564) -append(564,[MISRA 2012 Rule 13.2, required]) @@ -1124,13 +1123,13 @@ /* While MISRA has declared this rule to be "undecidable", Gimpel * Software provides the following options to assist: */ - +e685 /* relational always evaluates to true/false */ + +e685 /* relational always evaluates to true/false */ +elib(685) -append(685,[MISRA 2012 Rule 14.3, required]) - +e774 /* boolean always evaluates to true/false */ + +e774 /* boolean always evaluates to true/false */ +elib(774) -append(774,[MISRA 2012 Rule 14.3, required]) - +e650 /* constant out of range for operator */ + +e650 /* constant out of range for operator */ +elib(650) -append(650,[MISRA 2012 Rule 14.3, required]) @@ -1297,7 +1296,7 @@ /**** Rule 17.3 (Mand) ************/ - +e718 /* symbol undeclared, assumed to return int */ + +e718 /* symbol undeclared, assumed to return int */ +elib(718) -append(718,[MISRA 2012 Rule 17.3, mandatory]) diff --git a/ports/msp430/README.url b/ports/msp430/README.url index e13e95f7..946c36db 100644 --- a/ports/msp430/README.url +++ b/ports/msp430/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/msp430.html +URL=https://www.state-machine.com/qpc/msp430.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/threadx/README.url b/ports/threadx/README.url index 4abe31a5..7edfc3a4 100644 --- a/ports/threadx/README.url +++ b/ports/threadx/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/threadx.html +URL=https://www.state-machine.com/qpc/threadx.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/threadx/qf_port.c b/ports/threadx/qf_port.c index 775a41e2..7d602e14 100644 --- a/ports/threadx/qf_port.c +++ b/ports/threadx/qf_port.c @@ -4,8 +4,8 @@ * @ingroup ports * @cond ****************************************************************************** -* Last updated for version 6.9.2a -* Last updated on 2021-01-26 +* Last updated for version 6.9.3 +* Last updated on 2021-04-08 * * Q u a n t u m L e a P s * ------------------------ @@ -87,20 +87,11 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, void const * const par) { UINT tx_prio; /* ThreadX priority corresponding to the QF priority prio */ - CHAR tx_name[4]; /* name passed to ThreadX queue and thread */ - - /* prepare the unique name of the form "Axx", - * where xx is a 2-digit QP priority of the Active Object - */ - tx_name[0] = 'A'; - tx_name[1] = '0' + (prio / 10U); - tx_name[2] = '0' + (prio % 10U); - tx_name[3] = '\0'; /* allege that the ThreadX queue is created successfully */ Q_ALLEGE_ID(210, tx_queue_create(&me->eQueue, - tx_name, + me->thread.tx_thread_name, TX_1_ULONG, (VOID *)qSto, (ULONG)(qLen * sizeof(ULONG))) @@ -118,7 +109,7 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, Q_ALLEGE_ID(220, tx_thread_create( &me->thread, /* ThreadX thread control block */ - tx_name, /* unique thread name */ + me->thread.tx_thread_name, /* unique thread name */ &thread_function, /* thread function */ (ULONG)me, /* thread parameter */ stkSto, /* stack start */ @@ -130,6 +121,20 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, == TX_SUCCESS); } /*..........................................................................*/ +void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) { + /* this function must be called before QACTIVE_START(), + * which implies that me->thread.tx_thread_name must not be used yet; + */ + Q_REQUIRE_ID(300, me->thread.tx_thread_name == (char_t *)0); + switch (attr1) { + case THREAD_NAME_ATTR: + /* temporarily store the name, cast 'const' away */ + me->thread.tx_thread_name = (char_t *)attr2; + break; + /* ... */ + } +} +/*..........................................................................*/ #ifndef Q_SPY bool QActive_post_(QActive * const me, QEvt const * const e, uint_fast16_t const margin) diff --git a/ports/threadx/qf_port.h b/ports/threadx/qf_port.h index 55de552c..94dff199 100644 --- a/ports/threadx/qf_port.h +++ b/ports/threadx/qf_port.h @@ -3,14 +3,14 @@ * @brief QF/C, port to ThreadX * @cond ****************************************************************************** -* Last updated for version 6.9.1 -* Last updated on 2020-09-08 +* Last updated for version 6.9.3 +* Last updated on 2021-04-08 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -55,6 +55,10 @@ #define QF_CRIT_ENTRY(stat_) ((stat_) = tx_interrupt_control(TX_INT_DISABLE)) #define QF_CRIT_EXIT(stat_) ((void)tx_interrupt_control(stat_)) +enum ThreadX_ThreadAttrs { + THREAD_NAME_ATTR +}; + #include "tx_api.h" /* ThreadX API */ #include "qep_port.h" /* QEP port */ @@ -94,7 +98,7 @@ /* internal implementation of scheduler locking/unlocking */ void QFSchedLock_(QFSchedLock * const lockStat, uint_fast8_t prio); void QFSchedUnlock_(QFSchedLock const * const lockStat); - extern UINT _tx_thread_system_state; /* internal TX interrupt counter */ + extern ULONG volatile _tx_thread_system_state; /* internal TX interrupt counter */ /* TreadX block pool operations... */ #define QF_EPOOL_TYPE_ TX_BLOCK_POOL diff --git a/ports/ucos-ii/README.url b/ports/ucos-ii/README.url index b0cd33dc..347d38b9 100644 --- a/ports/ucos-ii/README.url +++ b/ports/ucos-ii/README.url @@ -1,3 +1,7 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/ucos-ii.html +URL=https://www.state-machine.com/qpc/ucos-ii.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/ucos-ii/qf_port.c b/ports/ucos-ii/qf_port.c index 2af8bea7..4f6efbbd 100644 --- a/ports/ucos-ii/qf_port.c +++ b/ports/ucos-ii/qf_port.c @@ -75,11 +75,6 @@ int_t QF_run(void) { void QF_stop(void) { QF_onCleanup(); /* cleanup callback */ } -/*..........................................................................*/ -void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) { - (void)attr2; /* unused parameter */ - me->thread = attr1; -} /*..........................................................................*/ void QActive_start_(QActive * const me, uint_fast8_t prio, @@ -89,7 +84,8 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, { INT8U p_ucos; INT8U err; - char_t task_name[4]; /* task name to be passed to OSTaskCreateExt() */ + /* task name to be passed to OSTaskCreateExt() */ + void *task_name = (void *)me->eQueue; me->eQueue = OSQCreate((void **)qSto, qLen); /* create uC/OS-II queue */ /* the uC/OS-II queue must be created correctly */ @@ -104,14 +100,6 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, /* map from QP to uC/OS priority */ p_ucos = (INT8U)(QF_MAX_ACTIVE - me->prio); - /* prepare the unique task name of the form "Axx", - * where xx is a 2-digit QP priority of the Active Object - */ - task_name[0] = 'A'; - task_name[1] = '0' + (prio / 10U); - task_name[2] = '0' + (prio % 10U); - task_name[3] = '\0'; /* zero-terminate */ - /* create AO's task... */ /* * NOTE: The call to uC/OS-II API OSTaskCreateExt() assumes that the @@ -136,6 +124,23 @@ void QActive_start_(QActive * const me, uint_fast8_t prio, /* uC/OS-II task must be created correctly */ Q_ENSURE_ID(220, err == OS_ERR_NONE); } +/*..........................................................................*/ +void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) { + switch (attr1) { + case TASK_NAME_ATTR: + /* this function must be called before QACTIVE_START(), + * which implies that me->eQueue must not be used yet; + */ + Q_ASSERT_ID(300, me->eQueue == (OS_EVENT *)0); + /* temporarily store the name, cast 'const' away */ + me->eQueue = (OS_EVENT *)attr2; + break; + /* ... */ + default: + me->thread = attr1; + break; + } +} /*..........................................................................*/ static void task_function(void *pdata) { /* uC/OS-II task signature */ diff --git a/ports/ucos-ii/qf_port.h b/ports/ucos-ii/qf_port.h index 35331bde..b9030cb8 100644 --- a/ports/ucos-ii/qf_port.h +++ b/ports/ucos-ii/qf_port.h @@ -3,14 +3,14 @@ * @brief QF/C generic port to uC/OS-II * @cond ****************************************************************************** -* Last updated for version 6.9.1 -* Last updated on 2020-09-08 +* Last updated for version 6.9.3 +* Last updated on 2021-04-08 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -61,6 +61,10 @@ #error Unsupported uC/OS-II critical section type #endif /* OS_CRITICAL_METHOD */ +enum UCOS2_TaskAttrs { + TASK_NAME_ATTR +}; + #include "qep_port.h" /* QEP port */ #include "qequeue.h" /* native QF event queue for deferring events */ #include "qmpool.h" /* native QF event pool */ diff --git a/ports/win32-qv/README.url b/ports/win32-qv/README.url index a8c4d235..5fcfb9ef 100644 --- a/ports/win32-qv/README.url +++ b/ports/win32-qv/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/win32-qv.html +URL=https://www.state-machine.com/qpc/win32-qv.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/ports/win32/README.url b/ports/win32/README.url index 2b580d97..33472cb0 100644 --- a/ports/win32/README.url +++ b/ports/win32/README.url @@ -1,4 +1,8 @@ [InternetShortcut] -URL=http://www.state-machine.com/qpc/win32.html +URL=https://www.state-machine.com/qpc/win32.html IconFile=http://www.state-machine.com/qp.ico +IDList= +HotKey=0 +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 diff --git a/src/qf/qf_dyn.c b/src/qf/qf_dyn.c index 83796fe6..59f8a74a 100644 --- a/src/qf/qf_dyn.c +++ b/src/qf/qf_dyn.c @@ -4,14 +4,14 @@ * @ingroup qf * @cond ****************************************************************************** -* Last updated for version 6.9.1 -* Last updated on 2020-09-03 +* Last updated for version 6.9.3 +* Last updated on 2021-04-09 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -201,7 +201,10 @@ QEvt *QF_newX_(uint_fast16_t const evtSize, } /* event cannot be allocated */ else { - /* must tolerate failed allocation */ + /* This assertion means that the event allocation failed, + * and this failure cannot be tolerated. The most frequent + * reason is an event leak in the application. + */ Q_ASSERT_ID(320, margin != QF_NO_MARGIN); QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, (uint_fast8_t)QS_EP_ID + idx + 1U) diff --git a/src/qf/qf_ps.c b/src/qf/qf_ps.c index cfc8c9c6..8eb8da75 100644 --- a/src/qf/qf_ps.c +++ b/src/qf/qf_ps.c @@ -4,14 +4,14 @@ * @ingroup qf * @cond ****************************************************************************** -* Last updated for version 6.9.1 -* Last updated on 2020-09-03 +* Last updated for version 6.9.3 +* Last updated on 2021-02-26 * * Q u a n t u m L e a P s * ------------------------ * Modern Embedded Software * -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. +* Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -118,7 +118,8 @@ void QF_psInit(QSubscrList * const subscrSto, enum_t const maxSignal) { #ifndef Q_SPY void QF_publish_(QEvt const * const e) #else -void QF_publish_(QEvt const * const e, void const * const sender) +void QF_publish_(QEvt const * const e, + void const * const sender, uint_fast8_t const qs_id) #endif { QPSet subscrList; /* local, modifiable copy of the subscriber list */ @@ -129,7 +130,7 @@ void QF_publish_(QEvt const * const e, void const * const sender) QF_CRIT_E_(); - QS_BEGIN_NOCRIT_PRE_(QS_QF_PUBLISH, 0U) + QS_BEGIN_NOCRIT_PRE_(QS_QF_PUBLISH, qs_id) QS_TIME_PRE_(); /* the timestamp */ QS_OBJ_PRE_(sender); /* the sender object */ QS_SIG_PRE_(e->sig); /* the signal of the event */ diff --git a/src/qs/qs_rx.c b/src/qs/qs_rx.c index d4129a73..d3d0a497 100644 --- a/src/qs/qs_rx.c +++ b/src/qs/qs_rx.c @@ -1059,7 +1059,7 @@ static void QS_rxHandleGoodFrame_(uint8_t state) { i = 0U; /* use 'i' as status, 0 == success,no-recycle */ if (l_rx.var.evt.prio == 0U) { /* publish */ - QF_PUBLISH(l_rx.var.evt.e, &QS_rxPriv_); + QF_publish_(l_rx.var.evt.e, &QS_rxPriv_, 0U); } else if (l_rx.var.evt.prio < QF_MAX_ACTIVE) { if (QACTIVE_POST_X(QF_active_[l_rx.var.evt.prio],