├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmsis-esp32 ├── cmsis-esp.c ├── include │ ├── cmsis_impl.h │ ├── cmsis_impl_logger.h │ ├── cmsis_impl_types.h │ ├── cmsis_os.h │ ├── cmsis_os2.h │ └── lwip.h └── lwip.c ├── dev_tool ├── README.md ├── build_example.bash ├── docker-compose.yml └── docker │ ├── build_mros2.bash │ └── esp_idf.dockerfile ├── platform ├── mros2-platform.cpp ├── mros2-platform.h ├── rtps │ └── config.h └── wifi │ ├── wifi.c │ └── wifi.h └── workspace ├── echoback_string ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── echoback_string.cpp ├── echoreply_string ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── echoreply_string.cpp ├── m5stack_sample ├── CMakeLists.txt ├── components │ └── .gitkeep └── main │ ├── CMakeLists.txt │ └── m5stack_sample.cpp ├── pub_float32 ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── pub_float32.cpp ├── pub_image ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ ├── mros_image.h │ └── pub_image.cpp ├── pub_long_string_sub_crc ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ ├── long_text.txt │ └── pub_long_string_sub_crc.cpp ├── pub_twist ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── pub_twist.cpp ├── sub_pose ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── sub_pose.cpp └── sub_uint16 ├── CMakeLists.txt └── main ├── CMakeLists.txt └── sub_uint16.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | sdkconfig 3 | *.old 4 | *.lock 5 | .env 6 | 7 | # The templates of pub/sub functions 8 | ## This file will be automatically generated/modified 9 | ## during the build step. So you do not have to care 10 | ## about this file. 11 | platform/templates.hpp 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mros2"] 2 | path = mros2 3 | url = https://github.com/mROS-base/mros2.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS "mros2/src/mros2.cpp" 2 | "mros2/embeddedRTPS/src/communication/UdpDriver.cpp" 3 | "mros2/embeddedRTPS/src/messages/MessageTypes.cpp" 4 | "mros2/embeddedRTPS/src/messages/MessageReceiver.cpp" 5 | "mros2/embeddedRTPS/src/discovery/TopicData.cpp" 6 | "mros2/embeddedRTPS/src/discovery/ParticipantProxyData.cpp" 7 | "mros2/embeddedRTPS/src/discovery/SEDPAgent.cpp" 8 | "mros2/embeddedRTPS/src/discovery/SPDPAgent.cpp" 9 | "mros2/embeddedRTPS/src/storages/PBufWrapper.cpp" 10 | "mros2/embeddedRTPS/src/ThreadPool.cpp" 11 | "mros2/embeddedRTPS/src/entities/Participant.cpp" 12 | "mros2/embeddedRTPS/src/entities/Domain.cpp" 13 | "mros2/embeddedRTPS/src/entities/StatelessReader.cpp" 14 | "mros2/embeddedRTPS/thirdparty/Micro-CDR/src/c/common.c" 15 | "mros2/embeddedRTPS/thirdparty/Micro-CDR/src/c/types/basic.c" 16 | "mros2/embeddedRTPS/thirdparty/Micro-CDR/src/c/types/string.c" 17 | "mros2/embeddedRTPS/thirdparty/Micro-CDR/src/c/types/sequence.c" 18 | "mros2/embeddedRTPS/thirdparty/Micro-CDR/src/c/types/array.c" 19 | "mros2/embeddedRTPS/thirdparty/lwip/default_netif.c" 20 | "cmsis-esp32/lwip.c" 21 | "cmsis-esp32/cmsis-esp.c" 22 | "platform/wifi/wifi.c" 23 | "platform/mros2-platform.cpp" 24 | ) 25 | 26 | set(INCS "mros2/include" 27 | "mros2/include/mros2" 28 | "mros2/mros2_msgs" 29 | "mros2/embeddedRTPS/include" 30 | "mros2/embeddedRTPS/thirdparty/lwip" 31 | "mros2/embeddedRTPS/thirdparty/Micro-CDR/include" 32 | "cmsis-esp32/include" 33 | "platform" 34 | "platform/wifi" 35 | ${CMAKE_SOURCE_DIR}/main 36 | ) 37 | 38 | if(NOT CMAKE_BUILD_EARLY_EXPANSION) 39 | add_compile_options(-w) 40 | endif() 41 | 42 | idf_component_register( 43 | SRCS ${SRCS} 44 | INCLUDE_DIRS ${INCS} 45 | REQUIRES nvs_flash esp_wifi) 46 | 47 | # Generate plaform/templates.hpp from mros2 application code 48 | ## You can add dir(s) in `--indir` if you have several dirs 49 | ## that contain application code files 50 | add_custom_command( 51 | OUTPUT templates.hpp 52 | COMMAND python3 ${COMPONENT_PATH}/mros2/mros2_header_generator/templates_generator.py --outdir ${COMPONENT_PATH}/platform --indir ${CMAKE_SOURCE_DIR}/main) 53 | add_custom_target(Template SOURCES templates.hpp) 54 | add_dependencies(${COMPONENT_LIB} Template) 55 | 56 | # Disable CONFIG_LWIP_IPV6 in `sdkconfig` in build process 57 | ## This realizes the same behavior by `idf.py menuconfig`. 58 | ## However, you need to do `idf.py build` twice to refrect 59 | ## all the settings properly. 60 | message(STATUS "PROJECT=${PROJECT_NAME}") 61 | add_custom_command( 62 | OUTPUT sdkconfig 63 | COMMAND grep -q CONFIG_LWIP_IPV6=y ${CMAKE_SOURCE_DIR}/sdkconfig || exit 0 && sed -i 's/CONFIG_LWIP_IPV6=y/CONFIG_LWIP_IPV6=n/g' ${CMAKE_SOURCE_DIR}/sdkconfig) 64 | add_custom_target(Sdkconfig SOURCES sdkconfig) 65 | add_dependencies(${COMPONENT_LIB} Sdkconfig) 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023 mROS-base 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mros2-esp32 2 | 3 | mROS 2 (`mros2` as casually codename) realizes a agent-less and lightweight runtime environment compatible with ROS 2 for embedded devices. 4 | mROS 2 mainly offers pub/sub APIs compatible with [rclcpp](https://docs.ros.org/en/rolling/p/rclcpp/index.html) for embedded devices. 5 | 6 | mROS 2 consists of communication library for pub/sub APIs, RTPS protocol, UDP/IP stack, and real-time kernel. 7 | This repository provides the reference implementation of mROS 2 that can be operated on the [Espressif Systems ESP32](https://www.espressif.com/en/products/socs/esp32) boards. 8 | Please also check [mros2 repository](https://github.com/mROS-base/mros2) for more details and another implementations. 9 | 10 | ## Supported environment 11 | 12 | - Target device: ESP32 family 13 | - Boards 14 | - For now, these boards below are confirmed to run the example on them. 15 | - [ESP32-S3-DevKitC-1](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html) 16 | - These boards below are also confirmed by the development team, but not always supported in the latest version (due to our development resources,,,). 17 | - [M5Stack Basic](http://docs.m5stack.com/en/core/basic) 18 | - [M5Stack Core2](http://docs.m5stack.com/en/core/core2) 19 | - [M5Stack CoreS3](http://docs.m5stack.com/en/core/CoreS3) 20 | - These boards were confirmed to operate by our friendly users (any PRs are welcome to add this list based on your experience!!) 21 | - [Seeed Studio XIAO ESP32C3](https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html) (see [#7](https://github.com/mROS-base/mros2-esp32/issues/7)) 22 | - [ESP32-C6-DevKitC-1](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/user_guide.html) (see [#21](https://github.com/mROS-base/mros2-esp32/issues/21)) 23 | - [Seeed Studio XIAO ESP32C6](https://www.seeedstudio.com/Seeed-Studio-XIAO-ESP32C6-p-5884.html) (see [#23](https://github.com/mROS-base/mros2-esp32/issues/23)) 24 | - [Seeed Studio XIAO ESP32S3](https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html) (see [#24](https://github.com/mROS-base/mros2-esp32/issues/24)) 25 | - SDK: [ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/index.html) 26 | - Kernel: [ESP-IDF FreeRTOS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos_idf.html) 27 | - Host environment 28 | - [ROS 2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) on Ubuntu 22.04 LTS 29 | - Network setting 30 | - Make sure both the device and the host are connected to the same network. 31 | - IP address needs to be assigned to the device by DHCP. We have not confirmed the operation using static IP setting yet. So you may not un-comment the `#define STATIC_IP` line in `platform/wifi/wifi.h`. 32 | - Please prepare the Wi-Fi router that provides 2.4 GHz band. 33 | - Most of ESP32 only support 2.4 GHz. 34 | - Note that you need to set up a dedicated SSID at 2.4 GHz. If the SSID has a band steering setting (that shares 2.4 GHz and 5 GHz), the communication of ESP32 may be disconnected during the operation. 35 | - The firewall on the host (Ubuntu) needs to be disabled for ROS 2 (DDS) communication (e.g. `$ sudo ufw disable`). 36 | - If the host is connected to the Internet with other network adapters, communication with mros2 may not work properly. In that case, please turn off them. 37 | 38 | ## Setup for development environment 39 | 40 | First, please install ESP-IDF as the toolchain for ESP32 family. 41 | We recommend to install it followed "Maunal Installation". 42 | https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html#manual-installation 43 | 44 | Currently, we checked the operation of basic sapmles with [esp-idf v5.1.1](https://github.com/espressif/esp-idf/releases/tag/v5.1.1). 45 | 46 | Building mros2 library requires [Jinja2](https://pypi.org/project/Jinja2/) (to generate `platform/templates.hpp` automatically). So please install this as the below. 47 | 48 | ``` 49 | $ pip install -U Jinja2 50 | ``` 51 | 52 | ## Quickstart only with this repository 53 | 54 | This repository contains mros2 libarary with its related implementations for ESP32, and some examples in [`workspace/`](workspace/). 55 | IOW, this repository is all you need to try it out about the power of mros2-esp32 right away!! 56 | This sections describes the quickstart with `workspace/echoback_string` as the examples. 57 | 58 | You can also use this repositoy as a component in your own ESP-IDF project. 59 | If you want to do so, please refer to [Usage into your own ESP-IDF project](#usage-into-your-own-esp-idf-project) in the next section. 60 | 61 | ### git clone 62 | 63 | Please `git clone` this repository with `--recursive` (mandatory). 64 | 65 | ``` 66 | git clone --recursive https://github.com/mROS-base/mros2-esp32.git 67 | cd mros2-esp32 68 | ``` 69 | 70 | Note that you cannot change the directory name from `mros2-esp32` since it is used as the component name in `CMakeLists.txt`. 71 | 72 | ### Setup your SSID and PASS 73 | 74 | Please setup SSID and PASS for your Wi-Fi AP in `platform/wifi/wifi.h` (be careful that we should not commit and push your network environment to the world :D) 75 | 76 | ```platform/wifi/wifi.h 77 | #define ESP_WIFI_SSID "SSID" 78 | #define ESP_WIFI_PASS "PASS" 79 | ``` 80 | 81 | Again, make sure that its SSID assigns IP by DHCP and is dedicated to 2.4 GHz band. 82 | 83 | ### Set target 84 | 85 | Go to `workspace/echoback_string/` and do the below to setup the target device. 86 | You need to adjust `` arg for your device (e.g., M5Stack Basic and Core2 for `esp32`, ESP32S3Dev and M5Stack CoreS3 for `esp32s3`) 87 | 88 | ``` 89 | cd workspace/echoback_string 90 | idf.py set-target esp32 91 | ``` 92 | 93 | Next, you need to disable IPv6 connection for lwIP, since RTPS communication cannot work well when it is enabled. 94 | Please do `idf.py menuconfig`, move to "Component config" -> "LWIP" -> "Enable IPv6" and --->" and type Space to disable it. 95 | 96 | The below image is from [@tasada038](https://github.com/tasada038)'s article: 「[mros2-esp32とM5Stackでサンプルプログラムを試す](https://zenn.dev/tasada038/articles/fdbf3e5ff7cd01)」 97 | 98 | [![](https://storage.googleapis.com/zenn-user-upload/667047c679bb-20230606.png)](https://zenn.dev/tasada038/articles/fdbf3e5ff7cd01#mros2-esp32%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E5%AE%9F%E8%A1%8C) 99 | 100 | If you are afraid to fiddle with this screen, you can skip this step because disabling IPv6 will be disabled automatically during the build process. 101 | However, you need to run the build twice in a row for proper configuration in this case. 102 | 103 | ### build, flash, and run! 104 | 105 | Please build the project as the below command. 106 | 107 | ``` 108 | idf.py build 109 | ``` 110 | 111 | When the build completed successfully, a binary is generated in `build/echoback_string.bin`. 112 | 113 | Connect the device to the host via USB cable, and flash the binary to it. 114 | The port `/tty/ttyUSB0` may be adjusted according to your target board and development environment. 115 | 116 | ``` 117 | idf.py -p /tty/ttyUSB0 flash 118 | ``` 119 | 120 | Finally, ron-yori-Run! 121 | You can observe the serial terminal by [IDF Monitor](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-monitor.html) 122 | (quit is `Ctrl + ]`). 123 | 124 | ``` 125 | $ idf.py -p /tty/ttyUSB0 monitor 126 | Executing action: monitor 127 | Running idf_monitor in directory /home/hogehoge/mros2-esp32/workspace/echoback_string 128 | ...(SNIPPED)... 129 | I (2208) esp_netif_handlers: sta ip: 192.168.11.102, mask: 255.255.255.0, gw: 192.168.11.1 130 | I (2208) wifi station: got ip:192.168.11.102 131 | I (2208) wifi station: connected to ap SSID:SSID password:PASS 132 | LOG_DEBUG : 00000000.182 : [MROS2LIB] set "192.168.11.102" for RTPS communication 133 | LOG_NOTICE : 00000000.182 : successfully connect and setup network 134 | --- 135 | LOG_NOTICE : 00000000.183 : mros2-esp32 start! 136 | LOG_NOTICE : 00000000.183 : app name: echoback_string 137 | LOG_DEBUG : 00000000.184 : [MROS2LIB] mros2_init task start 138 | LOG_DEBUG : 00000000.184 : [MROS2LIB] Initilizing lwIP complete 139 | LOG_DEBUG : 00000000.185 : mROS 2 initialization is completed 140 | LOG_DEBUG : 00000000.186 : [MROS2LIB] create_node 141 | LOG_DEBUG : 00000000.186 : [MROS2LIB] start creating participant 142 | LOG_DEBUG : 00000000.187 : [MROS2LIB] successfully created participant 143 | LOG_DEBUG : 00000000.187 : [MROS2LIB] create_publisher complete. 144 | LOG_DEBUG : 00000000.188 : [MROS2LIB] create_subscription complete. 145 | LOG_DEBUG : 00000000.195 : [MROS2LIB] Initilizing Domain complete 146 | LOG_NOTICE : 00000000.198 : ready to pub/sub message 147 | --- 148 | LOG_NOTICE : 00000000.198 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 0' 149 | LOG_NOTICE : 00000000.298 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 1' 150 | LOG_NOTICE : 00000000.398 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 2' 151 | LOG_NOTICE : 00000000.498 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 3' 152 | ...(SNIPPED)... 153 | ``` 154 | 155 | You can confirm proper connection with your AP (SSID and PASS), and gotten IP address that will also be set for RTPS communication. 156 | 157 | To confirm the operation of this echoback_string example, please operate [mros2-host-examples/mros2_echoreply_string](https://github.com/mROS-base/mros2-host-examples#mros2_echoreply_string) node on the ROS 2 host as the below. 158 | 159 | ``` 160 | $ ros2 run mros2_echoreply_string echoreply_node 161 | [INFO] [1695193182.117751738] [mros2_echoreply_node]: 162 | Subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 11' 163 | [INFO] [1695193182.117877196] [mros2_echoreply_node]: 164 | Publishing msg: 'Hello from mros2-esp32 onto "ESP32": 11' 165 | [INFO] [1695193183.115781171] [mros2_echoreply_node]: 166 | Subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 12' 167 | [INFO] [1695193183.115852751] [mros2_echoreply_node]: 168 | Publishing msg: 'Hello from mros2-esp32 onto "ESP32": 12' 169 | [INFO] [1695193184.160837237] [mros2_echoreply_node]: 170 | Subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 13' 171 | [INFO] [1695193184.160930132] [mros2_echoreply_node]: 172 | Publishing msg: 'Hello from mros2-esp32 onto "ESP32": 13' 173 | [INFO] [1695193185.185828052] [mros2_echoreply_node]: 174 | Subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 14' 175 | [INFO] [1695193185.185916568] [mros2_echoreply_node]: 176 | Publishing msg: 'Hello from mros2-esp32 onto "ESP32": 14' 177 | ...(SNIPPED)... 178 | ``` 179 | 180 | After that, mros2-esp32 and ROS 2 host can be connected directly via RTPS! 181 | 182 | ``` 183 | ...(SNIPPED)... 184 | LOG_NOTICE : 00000001.245 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 9' 185 | LOG_NOTICE : 00000001.345 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 10' 186 | LOG_DEBUG : 00000001.397 : [MROS2LIB] publisher matched with remote subscriber 187 | LOG_NOTICE : 00000001.445 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 11' 188 | LOG_NOTICE : 00000001.446 : subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 11' 189 | LOG_NOTICE : 00000001.545 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 12' 190 | LOG_NOTICE : 00000001.545 : subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 12' 191 | LOG_DEBUG : 00000001.611 : [MROS2LIB] subscriber matched with remote publisher 192 | LOG_NOTICE : 00000001.645 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 13' 193 | LOG_NOTICE : 00000001.650 : subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 13' 194 | LOG_NOTICE : 00000001.745 : publishing msg: 'Hello from mros2-esp32 onto "ESP32": 14' 195 | LOG_NOTICE : 00000001.755 : subscribed msg: 'Hello from mros2-esp32 onto "ESP32": 14' 196 | ...(SNIPPED)... 197 | ``` 198 | 199 | ### Examples 200 | 201 | This repository contains some example applications in [workspace/](workspace/) to communicate with ROS 2 nodes on the host. 202 | 203 | The followings are the basic communication examples to the host. 204 | The description and host operation of them are almost the same with [mros2-mbed#Examples](https://github.com/mROS-base/mros2-mbed#examples) (link is to mros2-mbed ripository). 205 | Please also check [mROS-base/mros2-host-examples](https://github.com/mROS-base/mros2-host-examples) repository for more detail about the host examples. 206 | 207 | - [echoback_string](https://github.com/mROS-base/mros2-mbed#echoback_string-default) 208 | - [echoreply_string](https://github.com/mROS-base/mros2-mbed#echoreply_string) 209 | - [pub_float32](https://github.com/mROS-base/mros2-mbed#pub_float32) 210 | - [pub_twist](https://github.com/mROS-base/mros2-mbed#pub_twist) 211 | - [sub_pose](https://github.com/mROS-base/mros2-mbed#sub_pose) 212 | - [sub_uint16](https://github.com/mROS-base/mros2-mbed#sub_uint16) 213 | 214 | The followings are under development and not confirmed the proper operation yet (also see [Issue#14](https://github.com/mROS-base/mros2-esp32/issues/14)) 215 | 216 | - [pub_image](https://github.com/mROS-base/mros2-mbed#pub_image) 217 | - [pub_long_string_sub_crc](https://github.com/mROS-base/mros2-mbed#pub_long_string_sub_crc) 218 | 219 | The followings is for M5Stack device. 220 | You need to do `git clone` [M5Unified](https://github.com/m5stack/M5Unified) and [M5GFX](https://github.com/m5stack/M5GFX) in `components/`, and use ESP-IDF v4.4.4 to try this sample due to the compatibility of these libraries. 221 | 222 | - m5stack_sample 223 | 224 | ## Usage into your own ESP-IDF project 225 | 226 | We are sure that you definiately want to use mros2-esp32 into your onw ESP-IDF project! 227 | 228 | This section introduce how to realize it, assuming the project name is "hello_mros2" and the location is `~/esp/`. 229 | 230 | ### Create your own project 231 | 232 | Go to your own location and create the `hello_mros2` project. 233 | 234 | ``` 235 | cd ~/esp 236 | idf.py create-project hello_mros2 237 | cd hello_mros2 238 | ``` 239 | 240 | ### Clone mros2-esp32 241 | 242 | First, create `./components` and do `git clone` into it (`--recursive` is mandatory). 243 | 244 | ``` 245 | mkdir components 246 | cd components/ 247 | git clone --recursive https://github.com/mROS-base/mros2-esp32 248 | ``` 249 | 250 | ### Change file type of source code 251 | 252 | You need to change filename (.ext) from `main/hello_mros2.c` to `main/hello_mros2.cpp` because you will use mros2 C++ APIs. 253 | 254 | ``` 255 | mv main/hello_mros2.c main/hello_mros2.cpp 256 | ``` 257 | 258 | ### Edit CMakeLists.txt 259 | 260 | You need to edit `./CMakeLists.txt` and `./main/CMakeLists.txt` as the below. 261 | 262 | - `./CMakeLists.txt` 263 | ``` 264 | cmake_minimum_required(VERSION 3.16) 265 | 266 | add_compile_options(-w) # add 267 | 268 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 269 | project(hello_mros2) 270 | ``` 271 | - This is due to avoid build error about `-Werror=format` in mros2-esp32 logging functions. See [#Issue16](https://github.com/mROS-base/mros2-esp32/issues/16) for details. 272 | - `./main/CMakeLists.txt` 273 | ``` 274 | idf_component_register(SRCS "hello_mros2.cpp" # edit 275 | INCLUDE_DIRS "." 276 | PRIV_REQUIRES "mros2-esp32") # add 277 | ``` 278 | 279 | ### Write your mros2 application 280 | 281 | The fastest way is to copy from [./workspace/echoback_string/main/echoback_string.cpp](https://github.com/mROS-base/mros2-esp32/blob/main/workspace/echoback_string/main/echoback_string.cpp) :D 282 | 283 | ``` 284 | cd ~/esp/hello_mros2 285 | cp components/mros2-esp32/workspace/echoback_string/main/echoback_string.cpp main/hello_mros2.cpp 286 | ``` 287 | 288 | ### Setup your SSID and PASS in mros2 lib 289 | 290 | You need to SSID and PASS for your Wi-Fi AP in `components/mros2-esp32/platform/wifi/wifi.h` (be careful that we should not commit and push your network environment to the world :D) 291 | 292 | ```platform/wifi/wifi.h 293 | #define ESP_WIFI_SSID "SSID" 294 | #define ESP_WIFI_PASS "PASS" 295 | ``` 296 | 297 | ### Then, set target, build, flash, and Run!! 298 | 299 | The rest of operations follow from [this subsection on Quickstart](#set-target). 300 | 301 | If you want to use your own customized message type followed by the ROS 2 manner, please refer to [mros2#generating-header-files-for-custom-msgtypes](https://github.com/mROS-base/mros2#generating-header-files-for-custom-msgtypes) section. 302 | 303 | Enjoy your mros2-esp32 development life!! :tada: 304 | 305 | ## Submodules and Licenses 306 | 307 | The source code of this repository itself is published under [Apache License 2.0](https://github.com/mROS-base/mros2/blob/main/LICENSE). 308 | Please note that this repository requires the following stacks as the submodules, and also check their Licenses. 309 | 310 | - [mros2](https://github.com/mROS-base/mros2): the pub/sub APIs compatible with ROS 2 Rclcpp 311 | - [embeddedRTPS](https://github.com/mROS-base/embeddedRTPS): RTPS communication layer (including lwIP and Micro-CDR) 312 | - [ESP-IDF and FreeRTOS](https://github.com/espressif/esp-idf): Espressif IoT Development Framework. Official development framework for Espressif SoCs. 313 | 314 | ## Awesome resources! 315 | 316 | The following are trial reports written by third-party users. We deeply appreciate your contributions! Of course, PR for adding your reports/articles, example of works are very welcome!! 317 | 318 | - [@tasada038](https://github.com/tasada038): 「[mros2-esp32とM5Stackでサンプルプログラムを試す](https://zenn.dev/tasada038/articles/fdbf3e5ff7cd01)」 319 | - [@Ar-Ray-code](https://github.com/Ar-Ray-code): 「[mros2-esp32をDocker内でビルドする](https://ar-ray.hatenablog.com/entry/2023/06/10/235333)」 320 | -------------------------------------------------------------------------------- /cmsis-esp32/cmsis-esp.c: -------------------------------------------------------------------------------- 1 | #include "cmsis_os.h" 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/task.h" 4 | #include "freertos/queue.h" 5 | 6 | osStatus_t osDelay(uint32_t ticks) 7 | { 8 | vTaskDelay(ticks / portTICK_PERIOD_MS); 9 | return osOK; 10 | } 11 | 12 | uint32_t osKernelGetTickCount(void) 13 | { 14 | return xTaskGetTickCount(); 15 | } 16 | 17 | osStatus_t osKernelStart(void) 18 | { 19 | return osOK; 20 | } 21 | 22 | osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) 23 | { 24 | xQueueReceive(mq_id, msg_ptr, timeout); 25 | return osOK; 26 | } 27 | 28 | osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) 29 | { 30 | return xQueueCreate(msg_count, msg_size); 31 | } 32 | 33 | osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) 34 | { 35 | TaskHandle_t xHandle; 36 | xTaskCreate(func, attr->name, attr->stack_size, argument, attr->priority, &xHandle); 37 | return xHandle; 38 | } 39 | 40 | osStatus_t osThreadTerminate(osThreadId_t thread_id) 41 | { 42 | vTaskDelete(thread_id); 43 | return osOK; 44 | } -------------------------------------------------------------------------------- /cmsis-esp32/include/cmsis_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef _CMSIS_IMPLE_H_ 2 | #define _CMSIS_IMPLE_H_ 3 | 4 | #include "cmsis_impl_logger.h" 5 | #include "cmsis_impl_types.h" 6 | 7 | #endif /* _CMSIS_IMPLE_H_ */ 8 | 9 | -------------------------------------------------------------------------------- /cmsis-esp32/include/cmsis_impl_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _CMSIS_IMPL_LOGGER_H_ 2 | #define _CMSIS_IMPL_LOGGER_H_ 3 | 4 | // #include "freertos_conversion.h" 5 | #include "cmsis_impl_types.h" 6 | 7 | #ifdef CMSIS_LOG_DISABLE_DEBUG 8 | #else 9 | #include 10 | #define syslog(flg, ...) \ 11 | do \ 12 | { \ 13 | uint32_t _tick = osKernelGetTickCount(); \ 14 | printf("%s : %08u.%03u : ", #flg, (_tick / 1000), (_tick % 1000)); \ 15 | printf(__VA_ARGS__); \ 16 | printf("\n"); \ 17 | } while (0) 18 | #endif 19 | 20 | /* 21 | * CMSIS LOG API 22 | */ 23 | #ifdef CMSIS_LOG_DISABLE_DEBUG 24 | #define CMSIS_IMPL_DEBUG(...) 25 | #else 26 | #define CMSIS_IMPL_DEBUG(...) syslog(LOG_DEBUG, __VA_ARGS__) 27 | #endif 28 | 29 | #ifdef CMSIS_LOG_DISABLE_INFO 30 | #define CMSIS_IMPL_INFO(...) 31 | #else 32 | #define CMSIS_IMPL_INFO(...) syslog(LOG_NOTICE, __VA_ARGS__) 33 | #endif 34 | 35 | #ifdef CMSIS_LOG_DISABLE_WARN 36 | #define CMSIS_IMPL_WARN(...) 37 | #else 38 | #define CMSIS_IMPL_WARN(...) syslog(LOG_WARNING, __VA_ARGS__) 39 | #endif 40 | 41 | #ifdef CMSIS_LOG_DISABLE_ERROR 42 | #define CMSIS_IMPL_ERROR(...) 43 | #else 44 | #define CMSIS_IMPL_ERROR(...) syslog(LOG_ERROR, __VA_ARGS__) 45 | #endif 46 | 47 | #ifdef CMSIS_LOG_DISABLE_FATAL 48 | #define CMSIS_IMPL_FATAL(...) 49 | #else 50 | #define CMSIS_IMPL_FATAL(...) syslog(LOG_EMERG, __VA_ARGS__) 51 | #endif 52 | 53 | #endif /* _CMSIS_IMPL_LOGGER_H_ */ 54 | -------------------------------------------------------------------------------- /cmsis-esp32/include/cmsis_impl_types.h: -------------------------------------------------------------------------------- 1 | #ifndef _CMSIS_TYPES_H_ 2 | #define _CMSIS_TYPES_H_ 3 | 4 | #include 5 | #include 6 | typedef unsigned short uint16_t; 7 | typedef unsigned int bool_t; 8 | #define Inline static inline 9 | #define false 0U 10 | #define true (!false) 11 | 12 | 13 | #endif /* _CMSIS_TYPES_H_ */ 14 | -------------------------------------------------------------------------------- /cmsis-esp32/include/cmsis_os.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 10. January 2017 21 | * $Revision: V2.1.0 22 | * 23 | * Project: CMSIS-RTOS API 24 | * Title: cmsis_os.h FreeRTOS header file 25 | * 26 | * Version 0.02 27 | * Initial Proposal Phase 28 | * Version 0.03 29 | * osKernelStart added, optional feature: main started as thread 30 | * osSemaphores have standard behavior 31 | * osTimerCreate does not start the timer, added osTimerStart 32 | * osThreadPass is renamed to osThreadYield 33 | * Version 1.01 34 | * Support for C++ interface 35 | * - const attribute removed from the osXxxxDef_t typedefs 36 | * - const attribute added to the osXxxxDef macros 37 | * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete 38 | * Added: osKernelInitialize 39 | * Version 1.02 40 | * Control functions for short timeouts in microsecond resolution: 41 | * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec 42 | * Removed: osSignalGet 43 | * Version 2.0.0 44 | * OS objects creation without macros (dynamic creation and resource allocation): 45 | * - added: osXxxxNew functions which replace osXxxxCreate 46 | * - added: osXxxxAttr_t structures 47 | * - deprecated: osXxxxCreate functions, osXxxxDef_t structures 48 | * - deprecated: osXxxxDef and osXxxx macros 49 | * osStatus codes simplified and renamed to osStatus_t 50 | * osEvent return structure deprecated 51 | * Kernel: 52 | * - added: osKernelInfo_t and osKernelGetInfo 53 | * - added: osKernelState_t and osKernelGetState (replaces osKernelRunning) 54 | * - added: osKernelLock, osKernelUnlock 55 | * - added: osKernelSuspend, osKernelResume 56 | * - added: osKernelGetTickCount, osKernelGetTickFreq 57 | * - renamed osKernelSysTick to osKernelGetSysTimerCount 58 | * - replaced osKernelSysTickFrequency with osKernelGetSysTimerFreq 59 | * - deprecated osKernelSysTickMicroSec 60 | * Thread: 61 | * - extended number of thread priorities 62 | * - renamed osPrioriry to osPrioriry_t 63 | * - replaced osThreadCreate with osThreadNew 64 | * - added: osThreadGetName 65 | * - added: osThreadState_t and osThreadGetState 66 | * - added: osThreadGetStackSize, osThreadGetStackSpace 67 | * - added: osThreadSuspend, osThreadResume 68 | * - added: osThreadJoin, osThreadDetach, osThreadExit 69 | * - added: osThreadGetCount, osThreadEnumerate 70 | * - added: Thread Flags (moved from Signals) 71 | * Signals: 72 | * - renamed osSignals to osThreadFlags (moved to Thread Flags) 73 | * - changed return value of Set/Clear/Wait functions 74 | * - Clear function limited to current running thread 75 | * - extended Wait function (options) 76 | * - added: osThreadFlagsGet 77 | * Event Flags: 78 | * - added new independent object for handling Event Flags 79 | * Delay and Wait functions: 80 | * - added: osDelayUntil 81 | * - deprecated: osWait 82 | * Timer: 83 | * - replaced osTimerCreate with osTimerNew 84 | * - added: osTimerGetName, osTimerIsRunning 85 | * Mutex: 86 | * - extended: attributes (Recursive, Priority Inherit, Robust) 87 | * - replaced osMutexCreate with osMutexNew 88 | * - renamed osMutexWait to osMutexAcquire 89 | * - added: osMutexGetName, osMutexGetOwner 90 | * Semaphore: 91 | * - extended: maximum and initial token count 92 | * - replaced osSemaphoreCreate with osSemaphoreNew 93 | * - renamed osSemaphoreWait to osSemaphoreAcquire (changed return value) 94 | * - added: osSemaphoreGetName, osSemaphoreGetCount 95 | * Memory Pool: 96 | * - using osMemoryPool prefix instead of osPool 97 | * - replaced osPoolCreate with osMemoryPoolNew 98 | * - extended osMemoryPoolAlloc (timeout) 99 | * - added: osMemoryPoolGetName 100 | * - added: osMemoryPoolGetCapacity, osMemoryPoolGetBlockSize 101 | * - added: osMemoryPoolGetCount, osMemoryPoolGetSpace 102 | * - added: osMemoryPoolDelete 103 | * - deprecated: osPoolCAlloc 104 | * Message Queue: 105 | * - extended: fixed size message instead of a single 32-bit value 106 | * - using osMessageQueue prefix instead of osMessage 107 | * - replaced osMessageCreate with osMessageQueueNew 108 | * - updated: osMessageQueuePut, osMessageQueueGet 109 | * - added: osMessageQueueGetName 110 | * - added: osMessageQueueGetCapacity, osMessageQueueGetMsgSize 111 | * - added: osMessageQueueGetCount, osMessageQueueGetSpace 112 | * - added: osMessageQueueReset, osMessageQueueDelete 113 | * Mail Queue: 114 | * - deprecated (superseded by extended Message Queue functionality) 115 | * Version 2.1.0 116 | * Support for critical and uncritical sections (nesting safe): 117 | * - updated: osKernelLock, osKernelUnlock 118 | * - added: osKernelRestoreLock 119 | * Updated Thread and Event Flags: 120 | * - changed flags parameter and return type from int32_t to uint32_t 121 | *---------------------------------------------------------------------------*/ 122 | 123 | #ifndef CMSIS_OS_H_ 124 | #define CMSIS_OS_H_ 125 | 126 | #include "cmsis_impl.h" 127 | 128 | #define RTOS_ID_n ((tskKERNEL_VERSION_MAJOR << 16) | (tskKERNEL_VERSION_MINOR)) 129 | #define RTOS_ID_s ("FreeRTOS " tskKERNEL_VERSION_NUMBER) 130 | 131 | #define osCMSIS 0x20001U ///< API version (main[31:16].sub[15:0]) 132 | 133 | #define osCMSIS_FreeRTOS RTOS_ID_n ///< RTOS identification and version (main[31:16].sub[15:0]) 134 | 135 | #define osKernelSystemId RTOS_ID_s ///< RTOS identification string 136 | 137 | #define osFeature_MainThread 0 ///< main thread 1=main can be thread, 0=not available 138 | #define osFeature_Signals 24U ///< maximum number of Signal Flags available per thread 139 | #define osFeature_Semaphore 65535U ///< maximum count for \ref osSemaphoreCreate function 140 | #define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available 141 | #define osFeature_SysTick 1 ///< osKernelSysTick functions: 1=available, 0=not available 142 | #define osFeature_Pool 0 ///< Memory Pools: 1=available, 0=not available 143 | #define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available 144 | #define osFeature_MailQ 0 ///< Mail Queues: 1=available, 0=not available 145 | 146 | #if defined(__CC_ARM) 147 | #define os_InRegs __value_in_regs 148 | #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 149 | #define os_InRegs __attribute__((value_in_regs)) 150 | #else 151 | #define os_InRegs 152 | #endif 153 | 154 | #include "cmsis_os2.h" 155 | 156 | #ifdef __cplusplus 157 | extern "C" 158 | { 159 | #endif 160 | 161 | // ==== Enumerations, structures, defines ==== 162 | 163 | /// Priority values. 164 | #if (osCMSIS < 0x20000U) 165 | typedef enum 166 | { 167 | osPriorityIdle = -3, ///< Priority: idle (lowest) 168 | osPriorityLow = -2, ///< Priority: low 169 | osPriorityBelowNormal = -1, ///< Priority: below normal 170 | osPriorityNormal = 0, ///< Priority: normal (default) 171 | osPriorityAboveNormal = +1, ///< Priority: above normal 172 | osPriorityHigh = +2, ///< Priority: high 173 | osPriorityRealtime = +3, ///< Priority: realtime (highest) 174 | osPriorityError = 0x84, ///< System cannot determine priority or illegal priority. 175 | osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. 176 | } osPriority; 177 | #else 178 | #define osPriority osPriority_t 179 | #endif 180 | 181 | /// Entry point of a thread. 182 | typedef void (*os_pthread)(void const *argument); 183 | 184 | /// Entry point of a timer call back function. 185 | typedef void (*os_ptimer)(void const *argument); 186 | 187 | /// Timer type. 188 | #if (osCMSIS < 0x20000U) 189 | typedef enum 190 | { 191 | osTimerOnce = 0, ///< One-shot timer. 192 | osTimerPeriodic = 1 ///< Repeating timer. 193 | } os_timer_type; 194 | #else 195 | #define os_timer_type osTimerType_t 196 | #endif 197 | 198 | /// Timeout value. 199 | #define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. 200 | 201 | /// Status code values returned by CMSIS-RTOS functions. 202 | #if (osCMSIS < 0x20000U) 203 | typedef enum 204 | { 205 | osOK = 0, ///< Function completed; no error or event occurred. 206 | osEventSignal = 0x08, ///< Function completed; signal event occurred. 207 | osEventMessage = 0x10, ///< Function completed; message event occurred. 208 | osEventMail = 0x20, ///< Function completed; mail event occurred. 209 | osEventTimeout = 0x40, ///< Function completed; timeout occurred. 210 | osErrorParameter = 0x80, ///< Parameter error: a mandatory parameter was missing or specified an incorrect object. 211 | osErrorResource = 0x81, ///< Resource not available: a specified resource was not available. 212 | osErrorTimeoutResource = 0xC1, ///< Resource not available within given time: a specified resource was not available within the timeout period. 213 | osErrorISR = 0x82, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines. 214 | osErrorISRRecursive = 0x83, ///< Function called multiple times from ISR with same object. 215 | osErrorPriority = 0x84, ///< System cannot determine priority or thread has illegal priority. 216 | osErrorNoMemory = 0x85, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation. 217 | osErrorValue = 0x86, ///< Value of a parameter is out of range. 218 | osErrorOS = 0xFF, ///< Unspecified RTOS error: run-time error but no other error message fits. 219 | osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. 220 | } osStatus; 221 | #else 222 | typedef int32_t osStatus; 223 | #define osEventSignal (0x08) 224 | #define osEventMessage (0x10) 225 | #define osEventMail (0x20) 226 | #define osEventTimeout (0x40) 227 | #define osErrorOS osError 228 | #define osErrorTimeoutResource osErrorTimeout 229 | #define osErrorISRRecursive (-126) 230 | #define osErrorValue (-127) 231 | #define osErrorPriority (-128) 232 | #endif 233 | 234 | // >>> the following data type definitions may be adapted towards a specific RTOS 235 | 236 | /// Thread ID identifies the thread. 237 | #if (osCMSIS < 0x20000U) 238 | typedef void *osThreadId; 239 | #else 240 | #define osThreadId osThreadId_t 241 | #endif 242 | 243 | /// Timer ID identifies the timer. 244 | #if (osCMSIS < 0x20000U) 245 | typedef void *osTimerId; 246 | #else 247 | #define osTimerId osTimerId_t 248 | #endif 249 | 250 | /// Mutex ID identifies the mutex. 251 | #if (osCMSIS < 0x20000U) 252 | typedef void *osMutexId; 253 | #else 254 | #define osMutexId osMutexId_t 255 | #endif 256 | 257 | /// Semaphore ID identifies the semaphore. 258 | #if (osCMSIS < 0x20000U) 259 | typedef void *osSemaphoreId; 260 | #else 261 | #define osSemaphoreId osSemaphoreId_t 262 | #endif 263 | 264 | /// Pool ID identifies the memory pool. 265 | typedef void *osPoolId; 266 | 267 | /// Message ID identifies the message queue. 268 | typedef void *osMessageQId; 269 | 270 | /// Mail ID identifies the mail queue. 271 | typedef void *osMailQId; 272 | 273 | /// Thread Definition structure contains startup information of a thread. 274 | #if (osCMSIS < 0x20000U) 275 | typedef struct os_thread_def 276 | { 277 | os_pthread pthread; ///< start address of thread function 278 | osPriority tpriority; ///< initial thread priority 279 | uint32_t instances; ///< maximum number of instances of that thread function 280 | uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size 281 | } osThreadDef_t; 282 | #else 283 | typedef struct os_thread_def 284 | { 285 | os_pthread pthread; ///< start address of thread function 286 | osThreadAttr_t attr; ///< thread attributes 287 | } osThreadDef_t; 288 | #endif 289 | 290 | /// Timer Definition structure contains timer parameters. 291 | #if (osCMSIS < 0x20000U) 292 | typedef struct os_timer_def 293 | { 294 | os_ptimer ptimer; ///< start address of a timer function 295 | } osTimerDef_t; 296 | #else 297 | typedef struct os_timer_def 298 | { 299 | os_ptimer ptimer; ///< start address of a timer function 300 | osTimerAttr_t attr; ///< timer attributes 301 | } osTimerDef_t; 302 | #endif 303 | 304 | /// Mutex Definition structure contains setup information for a mutex. 305 | #if (osCMSIS < 0x20000U) 306 | typedef struct os_mutex_def 307 | { 308 | uint32_t dummy; ///< dummy value 309 | } osMutexDef_t; 310 | #else 311 | #define osMutexDef_t osMutexAttr_t 312 | #endif 313 | 314 | /// Semaphore Definition structure contains setup information for a semaphore. 315 | #if (osCMSIS < 0x20000U) 316 | typedef struct os_semaphore_def 317 | { 318 | uint32_t dummy; ///< dummy value 319 | } osSemaphoreDef_t; 320 | #else 321 | #define osSemaphoreDef_t osSemaphoreAttr_t 322 | #endif 323 | 324 | /// Definition structure for memory block allocation. 325 | #if (osCMSIS < 0x20000U) 326 | typedef struct os_pool_def 327 | { 328 | uint32_t pool_sz; ///< number of items (elements) in the pool 329 | uint32_t item_sz; ///< size of an item 330 | void *pool; ///< pointer to memory for pool 331 | } osPoolDef_t; 332 | #else 333 | typedef struct os_pool_def 334 | { 335 | uint32_t pool_sz; ///< number of items (elements) in the pool 336 | uint32_t item_sz; ///< size of an item 337 | osMemoryPoolAttr_t attr; ///< memory pool attributes 338 | } osPoolDef_t; 339 | #endif 340 | 341 | /// Definition structure for message queue. 342 | #if (osCMSIS < 0x20000U) 343 | typedef struct os_messageQ_def 344 | { 345 | uint32_t queue_sz; ///< number of elements in the queue 346 | void *pool; ///< memory array for messages 347 | } osMessageQDef_t; 348 | #else 349 | typedef struct os_messageQ_def 350 | { 351 | uint32_t queue_sz; ///< number of elements in the queue 352 | osMessageQueueAttr_t attr; ///< message queue attributes 353 | } osMessageQDef_t; 354 | #endif 355 | 356 | /// Definition structure for mail queue. 357 | #if (osCMSIS < 0x20000U) 358 | typedef struct os_mailQ_def 359 | { 360 | uint32_t queue_sz; ///< number of elements in the queue 361 | uint32_t item_sz; ///< size of an item 362 | void *pool; ///< memory array for mail 363 | } osMailQDef_t; 364 | #else 365 | typedef struct os_mailQ_def 366 | { 367 | uint32_t queue_sz; ///< number of elements in the queue 368 | uint32_t item_sz; ///< size of an item 369 | void *mail; ///< pointer to mail 370 | osMemoryPoolAttr_t mp_attr; ///< memory pool attributes 371 | osMessageQueueAttr_t mq_attr; ///< message queue attributes 372 | } osMailQDef_t; 373 | #endif 374 | 375 | /// Event structure contains detailed information about an event. 376 | typedef struct 377 | { 378 | osStatus status; ///< status code: event or error information 379 | union 380 | { 381 | uint32_t v; ///< message as 32-bit value 382 | void *p; ///< message or mail as void pointer 383 | int32_t signals; ///< signal flags 384 | } value; ///< event value 385 | union 386 | { 387 | osMailQId mail_id; ///< mail id obtained by \ref osMailCreate 388 | osMessageQId message_id; ///< message id obtained by \ref osMessageCreate 389 | } def; ///< event definition 390 | } osEvent; 391 | 392 | // ==== Kernel Management Functions ==== 393 | 394 | /// Initialize the RTOS Kernel for creating objects. 395 | /// \return status code that indicates the execution status of the function. 396 | #if (osCMSIS < 0x20000U) 397 | osStatus osKernelInitialize(void); 398 | #endif 399 | 400 | /// Start the RTOS Kernel scheduler. 401 | /// \return status code that indicates the execution status of the function. 402 | #if (osCMSIS < 0x20000U) 403 | osStatus osKernelStart(void); 404 | #endif 405 | 406 | /// Check if the RTOS kernel is already started. 407 | /// \return 0 RTOS is not started, 1 RTOS is started. 408 | #if (osCMSIS < 0x20000U) 409 | int32_t osKernelRunning(void); 410 | #endif 411 | 412 | #if (defined(osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available 413 | 414 | /// Get the RTOS kernel system timer counter. 415 | /// \return RTOS kernel system timer as 32-bit value 416 | #if (osCMSIS < 0x20000U) 417 | uint32_t osKernelSysTick(void); 418 | #else 419 | #define osKernelSysTick osKernelGetSysTimerCount 420 | #endif 421 | 422 | /// The RTOS kernel system timer frequency in Hz. 423 | /// \note Reflects the system timer setting and is typically defined in a configuration file. 424 | #if (osCMSIS < 0x20000U) 425 | #define osKernelSysTickFrequency 100000000 426 | #endif 427 | 428 | /// Convert a microseconds value to a RTOS kernel system timer value. 429 | /// \param microsec time value in microseconds. 430 | /// \return time value normalized to the \ref osKernelSysTickFrequency 431 | #if (osCMSIS < 0x20000U) 432 | #define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000) 433 | #else 434 | #define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * osKernelGetSysTimerFreq()) / 1000000) 435 | #endif 436 | 437 | #endif // System Timer available 438 | 439 | // ==== Thread Management Functions ==== 440 | 441 | /// Create a Thread Definition with function, priority, and stack requirements. 442 | /// \param name name of the thread function. 443 | /// \param priority initial priority of the thread function. 444 | /// \param instances number of possible thread instances. 445 | /// \param stacksz stack size (in bytes) requirements for the thread function. 446 | #if defined(osObjectsExternal) // object is external 447 | #define osThreadDef(name, priority, instances, stacksz) \ 448 | extern const osThreadDef_t os_thread_def_##name 449 | #else // define the object 450 | #define osThreadDef(name, priority, instances, stacksz) \ 451 | static uint64_t os_thread_stack##name[(stacksz) ? (((stacksz + 7) / 8)) : 1]; \ 452 | static StaticTask_t os_thread_cb_##name; \ 453 | const osThreadDef_t os_thread_def_##name = \ 454 | {(name), \ 455 | {NULL, osThreadDetached, \ 456 | (instances == 1) ? (&os_thread_cb_##name) : NULL, \ 457 | (instances == 1) ? sizeof(StaticTask_t) : 0U, \ 458 | ((stacksz) && (instances == 1)) ? (&os_thread_stack##name) : NULL, \ 459 | 8 * ((stacksz + 7) / 8), \ 460 | (priority), 0U, 0U}} 461 | #endif 462 | 463 | /// Access a Thread definition. 464 | /// \param name name of the thread definition object. 465 | #define osThread(name) \ 466 | &os_thread_def_##name 467 | 468 | /// Create a thread and add it to Active Threads and set it to state READY. 469 | /// \param[in] thread_def thread definition referenced with \ref osThread. 470 | /// \param[in] argument pointer that is passed to the thread function as start argument. 471 | /// \return thread ID for reference by other functions or NULL in case of error. 472 | osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument); 473 | 474 | /// Return the thread ID of the current running thread. 475 | /// \return thread ID for reference by other functions or NULL in case of error. 476 | #if (osCMSIS < 0x20000U) 477 | osThreadId osThreadGetId(void); 478 | #endif 479 | 480 | /// Change priority of a thread. 481 | /// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. 482 | /// \param[in] priority new priority value for the thread function. 483 | /// \return status code that indicates the execution status of the function. 484 | #if (osCMSIS < 0x20000U) 485 | osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority); 486 | #endif 487 | 488 | /// Get current priority of a thread. 489 | /// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. 490 | /// \return current priority value of the specified thread. 491 | #if (osCMSIS < 0x20000U) 492 | osPriority osThreadGetPriority(osThreadId thread_id); 493 | #endif 494 | 495 | /// Pass control to next thread that is in state \b READY. 496 | /// \return status code that indicates the execution status of the function. 497 | #if (osCMSIS < 0x20000U) 498 | osStatus osThreadYield(void); 499 | #endif 500 | 501 | /// Terminate execution of a thread. 502 | /// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. 503 | /// \return status code that indicates the execution status of the function. 504 | #if (osCMSIS < 0x20000U) 505 | osStatus osThreadTerminate(osThreadId thread_id); 506 | #endif 507 | 508 | // ==== Signal Management ==== 509 | 510 | /// Set the specified Signal Flags of an active thread. 511 | /// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. 512 | /// \param[in] signals specifies the signal flags of the thread that should be set. 513 | /// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. 514 | int32_t osSignalSet(osThreadId thread_id, int32_t signals); 515 | 516 | /// Clear the specified Signal Flags of an active thread. 517 | /// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. 518 | /// \param[in] signals specifies the signal flags of the thread that shall be cleared. 519 | /// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters or call from ISR. 520 | int32_t osSignalClear(osThreadId thread_id, int32_t signals); 521 | 522 | /// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. 523 | /// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag. 524 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 525 | /// \return event flag information or error code. 526 | os_InRegs osEvent osSignalWait(int32_t signals, uint32_t millisec); 527 | 528 | // ==== Generic Wait Functions ==== 529 | 530 | /// Wait for Timeout (Time Delay). 531 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "time delay" value 532 | /// \return status code that indicates the execution status of the function. 533 | #if (osCMSIS < 0x20000U) 534 | osStatus osDelay(uint32_t millisec); 535 | #endif 536 | 537 | #if (defined(osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available 538 | 539 | /// Wait for Signal, Message, Mail, or Timeout. 540 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out 541 | /// \return event that contains signal, message, or mail information or error code. 542 | os_InRegs osEvent osWait(uint32_t millisec); 543 | 544 | #endif // Generic Wait available 545 | 546 | // ==== Timer Management Functions ==== 547 | 548 | /// Define a Timer object. 549 | /// \param name name of the timer object. 550 | /// \param function name of the timer call back function. 551 | #if defined(osObjectsExternal) // object is external 552 | #define osTimerDef(name, function) \ 553 | extern const osTimerDef_t os_timer_def_##name 554 | #else // define the object 555 | #define osTimerDef(name, function) \ 556 | static StaticTimer_t os_timer_cb_##name; \ 557 | const osTimerDef_t os_timer_def_##name = \ 558 | {(function), {NULL, 0U, (&os_timer_cb_##name), sizeof(StaticTimer_t)}} 559 | #endif 560 | 561 | /// Access a Timer definition. 562 | /// \param name name of the timer object. 563 | #define osTimer(name) \ 564 | &os_timer_def_##name 565 | 566 | /// Create and Initialize a timer. 567 | /// \param[in] timer_def timer object referenced with \ref osTimer. 568 | /// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. 569 | /// \param[in] argument argument to the timer call back function. 570 | /// \return timer ID for reference by other functions or NULL in case of error. 571 | osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument); 572 | 573 | /// Start or restart a timer. 574 | /// \param[in] timer_id timer ID obtained by \ref osTimerCreate. 575 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "time delay" value of the timer. 576 | /// \return status code that indicates the execution status of the function. 577 | #if (osCMSIS < 0x20000U) 578 | osStatus osTimerStart(osTimerId timer_id, uint32_t millisec); 579 | #endif 580 | 581 | /// Stop a timer. 582 | /// \param[in] timer_id timer ID obtained by \ref osTimerCreate. 583 | /// \return status code that indicates the execution status of the function. 584 | #if (osCMSIS < 0x20000U) 585 | osStatus osTimerStop(osTimerId timer_id); 586 | #endif 587 | 588 | /// Delete a timer. 589 | /// \param[in] timer_id timer ID obtained by \ref osTimerCreate. 590 | /// \return status code that indicates the execution status of the function. 591 | #if (osCMSIS < 0x20000U) 592 | osStatus osTimerDelete(osTimerId timer_id); 593 | #endif 594 | 595 | // ==== Mutex Management Functions ==== 596 | 597 | /// Define a Mutex. 598 | /// \param name name of the mutex object. 599 | #if defined(osObjectsExternal) // object is external 600 | #define osMutexDef(name) \ 601 | extern const osMutexDef_t os_mutex_def_##name 602 | #else // define the object 603 | #define osMutexDef(name) \ 604 | static StaticSemaphore_t os_mutex_cb_##name; \ 605 | const osMutexDef_t os_mutex_def_##name = \ 606 | {NULL, osMutexRecursive | osMutexPrioInherit, (&os_mutex_cb_##name), sizeof(StaticSemaphore_t)} 607 | #endif 608 | 609 | /// Access a Mutex definition. 610 | /// \param name name of the mutex object. 611 | #define osMutex(name) \ 612 | &os_mutex_def_##name 613 | 614 | /// Create and Initialize a Mutex object. 615 | /// \param[in] mutex_def mutex definition referenced with \ref osMutex. 616 | /// \return mutex ID for reference by other functions or NULL in case of error. 617 | osMutexId osMutexCreate(const osMutexDef_t *mutex_def); 618 | 619 | /// Wait until a Mutex becomes available. 620 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. 621 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 622 | /// \return status code that indicates the execution status of the function. 623 | #if (osCMSIS < 0x20000U) 624 | osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec); 625 | #else 626 | #define osMutexWait osMutexAcquire 627 | #endif 628 | 629 | /// Release a Mutex that was obtained by \ref osMutexWait. 630 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. 631 | /// \return status code that indicates the execution status of the function. 632 | #if (osCMSIS < 0x20000U) 633 | osStatus osMutexRelease(osMutexId mutex_id); 634 | #endif 635 | 636 | /// Delete a Mutex object. 637 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. 638 | /// \return status code that indicates the execution status of the function. 639 | #if (osCMSIS < 0x20000U) 640 | osStatus osMutexDelete(osMutexId mutex_id); 641 | #endif 642 | 643 | // ==== Semaphore Management Functions ==== 644 | 645 | #if (defined(osFeature_Semaphore) && (osFeature_Semaphore != 0U)) // Semaphore available 646 | 647 | /// Define a Semaphore object. 648 | /// \param name name of the semaphore object. 649 | #if defined(osObjectsExternal) // object is external 650 | #define osSemaphoreDef(name) \ 651 | extern const osSemaphoreDef_t os_semaphore_def_##name 652 | #else // define the object 653 | #define osSemaphoreDef(name) \ 654 | static StaticSemaphore_t os_semaphore_cb_##name; \ 655 | const osSemaphoreDef_t os_semaphore_def_##name = \ 656 | {NULL, 0U, (&os_semaphore_cb_##name), sizeof(StaticSemaphore_t)} 657 | #endif 658 | 659 | /// Access a Semaphore definition. 660 | /// \param name name of the semaphore object. 661 | #define osSemaphore(name) \ 662 | &os_semaphore_def_##name 663 | 664 | /// Create and Initialize a Semaphore object. 665 | /// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore. 666 | /// \param[in] count maximum and initial number of available tokens. 667 | /// \return semaphore ID for reference by other functions or NULL in case of error. 668 | osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count); 669 | 670 | /// Wait until a Semaphore token becomes available. 671 | /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. 672 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 673 | /// \return number of available tokens, or -1 in case of incorrect parameters. 674 | int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec); 675 | 676 | /// Release a Semaphore token. 677 | /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. 678 | /// \return status code that indicates the execution status of the function. 679 | #if (osCMSIS < 0x20000U) 680 | osStatus osSemaphoreRelease(osSemaphoreId semaphore_id); 681 | #endif 682 | 683 | /// Delete a Semaphore object. 684 | /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. 685 | /// \return status code that indicates the execution status of the function. 686 | #if (osCMSIS < 0x20000U) 687 | osStatus osSemaphoreDelete(osSemaphoreId semaphore_id); 688 | #endif 689 | 690 | #endif // Semaphore available 691 | 692 | // ==== Memory Pool Management Functions ==== 693 | 694 | #if (defined(osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool available 695 | 696 | /// \brief Define a Memory Pool. 697 | /// \param name name of the memory pool. 698 | /// \param no maximum number of blocks (objects) in the memory pool. 699 | /// \param type data type of a single block (object). 700 | #if defined(osObjectsExternal) // object is external 701 | #define osPoolDef(name, no, type) \ 702 | extern const osPoolDef_t os_pool_def_##name 703 | #else // define the object 704 | #define osPoolDef(name, no, type) \ 705 | const osPoolDef_t os_pool_def_##name = \ 706 | {(no), sizeof(type), {NULL}} 707 | #endif 708 | 709 | /// \brief Access a Memory Pool definition. 710 | /// \param name name of the memory pool 711 | #define osPool(name) \ 712 | &os_pool_def_##name 713 | 714 | /// Create and Initialize a Memory Pool object. 715 | /// \param[in] pool_def memory pool definition referenced with \ref osPool. 716 | /// \return memory pool ID for reference by other functions or NULL in case of error. 717 | osPoolId osPoolCreate(const osPoolDef_t *pool_def); 718 | 719 | /// Allocate a memory block from a Memory Pool. 720 | /// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. 721 | /// \return address of the allocated memory block or NULL in case of no memory available. 722 | void *osPoolAlloc(osPoolId pool_id); 723 | 724 | /// Allocate a memory block from a Memory Pool and set memory block to zero. 725 | /// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. 726 | /// \return address of the allocated memory block or NULL in case of no memory available. 727 | void *osPoolCAlloc(osPoolId pool_id); 728 | 729 | /// Return an allocated memory block back to a Memory Pool. 730 | /// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. 731 | /// \param[in] block address of the allocated memory block to be returned to the memory pool. 732 | /// \return status code that indicates the execution status of the function. 733 | osStatus osPoolFree(osPoolId pool_id, void *block); 734 | 735 | #endif // Memory Pool available 736 | 737 | // ==== Message Queue Management Functions ==== 738 | 739 | #if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queue available 740 | 741 | /// \brief Create a Message Queue Definition. 742 | /// \param name name of the queue. 743 | /// \param queue_sz maximum number of messages in the queue. 744 | /// \param type data type of a single message element (for debugger). 745 | #if defined(osObjectsExternal) // object is external 746 | #define osMessageQDef(name, queue_sz, type) \ 747 | extern const osMessageQDef_t os_messageQ_def_##name 748 | #else // define the object 749 | #define osMessageQDef(name, queue_sz, type) \ 750 | static StaticQueue_t os_mq_cb_##name; \ 751 | static uint32_t os_mq_data_##name[(queue_sz) * sizeof(type)]; \ 752 | const osMessageQDef_t os_messageQ_def_##name = \ 753 | {(queue_sz), \ 754 | {NULL, 0U, (&os_mq_cb_##name), sizeof(StaticQueue_t), \ 755 | (&os_mq_data_##name), sizeof(os_mq_data_##name)}} 756 | #endif 757 | 758 | /// \brief Access a Message Queue Definition. 759 | /// \param name name of the queue 760 | #define osMessageQ(name) \ 761 | &os_messageQ_def_##name 762 | 763 | /// Create and Initialize a Message Queue object. 764 | /// \param[in] queue_def message queue definition referenced with \ref osMessageQ. 765 | /// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. 766 | /// \return message queue ID for reference by other functions or NULL in case of error. 767 | osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id); 768 | 769 | /// Put a Message to a Queue. 770 | /// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. 771 | /// \param[in] info message information. 772 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 773 | /// \return status code that indicates the execution status of the function. 774 | osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec); 775 | 776 | /// Get a Message from a Queue or timeout if Queue is empty. 777 | /// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. 778 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 779 | /// \return event information that includes status code. 780 | os_InRegs osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec); 781 | 782 | #endif // Message Queue available 783 | 784 | // ==== Mail Queue Management Functions ==== 785 | 786 | #if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queue available 787 | 788 | /// \brief Create a Mail Queue Definition. 789 | /// \param name name of the queue. 790 | /// \param queue_sz maximum number of mails in the queue. 791 | /// \param type data type of a single mail element. 792 | #if defined(osObjectsExternal) // object is external 793 | #define osMailQDef(name, queue_sz, type) \ 794 | extern const osMailQDef_t os_mailQ_def_##name 795 | #else // define the object 796 | #define osMailQDef(name, queue_sz, type) \ 797 | const osMailQDef_t os_mailQ_def_##name = \ 798 | {(queue_sz), sizeof(type), NULL} 799 | #endif 800 | 801 | /// \brief Access a Mail Queue Definition. 802 | /// \param name name of the queue 803 | #define osMailQ(name) \ 804 | &os_mailQ_def_##name 805 | 806 | /// Create and Initialize a Mail Queue object. 807 | /// \param[in] queue_def mail queue definition referenced with \ref osMailQ. 808 | /// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. 809 | /// \return mail queue ID for reference by other functions or NULL in case of error. 810 | osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id); 811 | 812 | /// Allocate a memory block for mail from a mail memory pool. 813 | /// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. 814 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out 815 | /// \return pointer to memory block that can be filled with mail or NULL in case of error. 816 | void *osMailAlloc(osMailQId queue_id, uint32_t millisec); 817 | 818 | /// Allocate a memory block for mail from a mail memory pool and set memory block to zero. 819 | /// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. 820 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out 821 | /// \return pointer to memory block that can be filled with mail or NULL in case of error. 822 | void *osMailCAlloc(osMailQId queue_id, uint32_t millisec); 823 | 824 | /// Put a Mail into a Queue. 825 | /// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. 826 | /// \param[in] mail pointer to memory with mail to put into a queue. 827 | /// \return status code that indicates the execution status of the function. 828 | osStatus osMailPut(osMailQId queue_id, const void *mail); 829 | 830 | /// Get a Mail from a Queue or timeout if Queue is empty. 831 | /// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. 832 | /// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 833 | /// \return event information that includes status code. 834 | os_InRegs osEvent osMailGet(osMailQId queue_id, uint32_t millisec); 835 | 836 | /// Free a memory block by returning it to a mail memory pool. 837 | /// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. 838 | /// \param[in] mail pointer to memory block that was obtained with \ref osMailGet. 839 | /// \return status code that indicates the execution status of the function. 840 | osStatus osMailFree(osMailQId queue_id, void *mail); 841 | 842 | #endif // Mail Queue available 843 | 844 | #ifdef __cplusplus 845 | } 846 | #endif 847 | 848 | #endif // CMSIS_OS_H_ 849 | -------------------------------------------------------------------------------- /cmsis-esp32/include/cmsis_os2.h: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | * Portions Copyright 息 2017 STMicroelectronics International N.V. All rights reserved. 3 | * Portions Copyright (c) 2013-2017 ARM Limited. All rights reserved. 4 | * -------------------------------------------------------------------------- 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the License); you may 9 | * not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | * Name: cmsis_os2.h 21 | * Purpose: CMSIS RTOS2 wrapper for FreeRTOS 22 | * 23 | *---------------------------------------------------------------------------*/ 24 | 25 | #ifndef CMSIS_OS2_H_ 26 | #define CMSIS_OS2_H_ 27 | 28 | #ifndef __NO_RETURN 29 | #if defined(__CC_ARM) 30 | #define __NO_RETURN __declspec(noreturn) 31 | #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 32 | #define __NO_RETURN __attribute__((__noreturn__)) 33 | #elif defined(__GNUC__) 34 | #define __NO_RETURN __attribute__((__noreturn__)) 35 | #elif defined(__ICCARM__) 36 | #define __NO_RETURN __noreturn 37 | #else 38 | #define __NO_RETURN 39 | #endif 40 | #endif 41 | 42 | #include 43 | #include 44 | 45 | #ifdef __cplusplus 46 | extern "C" 47 | { 48 | #endif 49 | 50 | 51 | // ==== Enumerations, structures, defines ==== 52 | 53 | /// Version information. 54 | typedef struct { 55 | uint32_t api; ///< API version (major.minor.rev: mmnnnrrrr dec). 56 | uint32_t kernel; ///< Kernel version (major.minor.rev: mmnnnrrrr dec). 57 | } osVersion_t; 58 | 59 | /// Kernel state. 60 | typedef enum { 61 | osKernelInactive = 0, ///< Inactive. 62 | osKernelReady = 1, ///< Ready. 63 | osKernelRunning = 2, ///< Running. 64 | osKernelLocked = 3, ///< Locked. 65 | osKernelSuspended = 4, ///< Suspended. 66 | osKernelError = -1, ///< Error. 67 | osKernelReserved = 0x7FFFFFFFU ///< Prevents enum down-size compiler optimization. 68 | } osKernelState_t; 69 | 70 | /// Thread state. 71 | typedef enum { 72 | osThreadInactive = 0, ///< Inactive. 73 | osThreadReady = 1, ///< Ready. 74 | osThreadRunning = 2, ///< Running. 75 | osThreadBlocked = 3, ///< Blocked. 76 | osThreadTerminated = 4, ///< Terminated. 77 | osThreadError = -1, ///< Error. 78 | osThreadReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. 79 | } osThreadState_t; 80 | 81 | /// Priority values. 82 | typedef enum { 83 | osPriorityNone = 0, ///< No priority (not initialized). 84 | osPriorityIdle = 1, ///< Reserved for Idle thread. 85 | osPriorityLow = 8, ///< Priority: low 86 | osPriorityLow1 = 8+1, ///< Priority: low + 1 87 | osPriorityLow2 = 8+2, ///< Priority: low + 2 88 | osPriorityLow3 = 8+3, ///< Priority: low + 3 89 | osPriorityLow4 = 8+4, ///< Priority: low + 4 90 | osPriorityLow5 = 8+5, ///< Priority: low + 5 91 | osPriorityLow6 = 8+6, ///< Priority: low + 6 92 | osPriorityLow7 = 8+7, ///< Priority: low + 7 93 | osPriorityBelowNormal = 16, ///< Priority: below normal 94 | osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1 95 | osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2 96 | osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3 97 | osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4 98 | osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5 99 | osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6 100 | osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7 101 | osPriorityNormal = 24, ///< Priority: normal 102 | osPriorityNormal1 = 24+1, ///< Priority: normal + 1 103 | osPriorityNormal2 = 24+2, ///< Priority: normal + 2 104 | osPriorityNormal3 = 24+3, ///< Priority: normal + 3 105 | osPriorityNormal4 = 24+4, ///< Priority: normal + 4 106 | osPriorityNormal5 = 24+5, ///< Priority: normal + 5 107 | osPriorityNormal6 = 24+6, ///< Priority: normal + 6 108 | osPriorityNormal7 = 24+7, ///< Priority: normal + 7 109 | osPriorityAboveNormal = 32, ///< Priority: above normal 110 | osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1 111 | osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2 112 | osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3 113 | osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4 114 | osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5 115 | osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6 116 | osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7 117 | osPriorityHigh = 40, ///< Priority: high 118 | osPriorityHigh1 = 40+1, ///< Priority: high + 1 119 | osPriorityHigh2 = 40+2, ///< Priority: high + 2 120 | osPriorityHigh3 = 40+3, ///< Priority: high + 3 121 | osPriorityHigh4 = 40+4, ///< Priority: high + 4 122 | osPriorityHigh5 = 40+5, ///< Priority: high + 5 123 | osPriorityHigh6 = 40+6, ///< Priority: high + 6 124 | osPriorityHigh7 = 40+7, ///< Priority: high + 7 125 | osPriorityRealtime = 48, ///< Priority: realtime 126 | osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1 127 | osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2 128 | osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3 129 | osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4 130 | osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5 131 | osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6 132 | osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7 133 | osPriorityISR = 56, ///< Reserved for ISR deferred thread. 134 | osPriorityError = -1, ///< System cannot determine priority or illegal priority. 135 | osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. 136 | } osPriority_t; 137 | 138 | /// Entry point of a thread. 139 | typedef void (*osThreadFunc_t) (void *argument); 140 | 141 | /// Timer callback function. 142 | typedef void (*osTimerFunc_t) (void *argument); 143 | 144 | /// Timer type. 145 | typedef enum { 146 | osTimerOnce = 0, ///< One-shot timer. 147 | osTimerPeriodic = 1 ///< Repeating timer. 148 | } osTimerType_t; 149 | 150 | // Timeout value. 151 | #define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. 152 | 153 | // Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait). 154 | #define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). 155 | #define osFlagsWaitAll 0x00000001U ///< Wait for all flags. 156 | #define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. 157 | 158 | // Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx). 159 | #define osFlagsError 0x80000000U ///< Error indicator. 160 | #define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1). 161 | #define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2). 162 | #define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3). 163 | #define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4). 164 | #define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6). 165 | 166 | // Thread attributes (attr_bits in \ref osThreadAttr_t). 167 | #define osThreadDetached 0x00000000U ///< Thread created in detached mode (default) 168 | #define osThreadJoinable 0x00000001U ///< Thread created in joinable mode 169 | 170 | // Mutex attributes (attr_bits in \ref osMutexAttr_t). 171 | #define osMutexRecursive 0x00000001U ///< Recursive mutex. 172 | #define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol. 173 | #define osMutexRobust 0x00000008U ///< Robust mutex. 174 | 175 | /// Status code values returned by CMSIS-RTOS functions. 176 | typedef enum { 177 | osOK = 0, ///< Operation completed successfully. 178 | osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits. 179 | osErrorTimeout = -2, ///< Operation not completed within the timeout period. 180 | osErrorResource = -3, ///< Resource not available. 181 | osErrorParameter = -4, ///< Parameter error. 182 | osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation. 183 | osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines. 184 | osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. 185 | } osStatus_t; 186 | 187 | 188 | /// \details Thread ID identifies the thread. 189 | typedef void *osThreadId_t; 190 | 191 | /// \details Timer ID identifies the timer. 192 | typedef void *osTimerId_t; 193 | 194 | /// \details Event Flags ID identifies the event flags. 195 | typedef void *osEventFlagsId_t; 196 | 197 | /// \details Mutex ID identifies the mutex. 198 | typedef void *osMutexId_t; 199 | 200 | /// \details Semaphore ID identifies the semaphore. 201 | typedef void *osSemaphoreId_t; 202 | 203 | /// \details Memory Pool ID identifies the memory pool. 204 | typedef void *osMemoryPoolId_t; 205 | 206 | /// \details Message Queue ID identifies the message queue. 207 | typedef void *osMessageQueueId_t; 208 | 209 | 210 | #ifndef TZ_MODULEID_T 211 | #define TZ_MODULEID_T 212 | /// \details Data type that identifies secure software modules called by a process. 213 | typedef uint32_t TZ_ModuleId_t; 214 | #endif 215 | 216 | 217 | /// Attributes structure for thread. 218 | typedef struct { 219 | const char *name; ///< name of the thread 220 | uint32_t attr_bits; ///< attribute bits 221 | void *cb_mem; ///< memory for control block 222 | uint32_t cb_size; ///< size of provided memory for control block 223 | void *stack_mem; ///< memory for stack 224 | uint32_t stack_size; ///< size of stack 225 | osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) 226 | TZ_ModuleId_t tz_module; ///< TrustZone module identifier 227 | uint32_t reserved; ///< reserved (must be 0) 228 | } osThreadAttr_t; 229 | 230 | /// Attributes structure for timer. 231 | typedef struct { 232 | const char *name; ///< name of the timer 233 | uint32_t attr_bits; ///< attribute bits 234 | void *cb_mem; ///< memory for control block 235 | uint32_t cb_size; ///< size of provided memory for control block 236 | } osTimerAttr_t; 237 | 238 | /// Attributes structure for event flags. 239 | typedef struct { 240 | const char *name; ///< name of the event flags 241 | uint32_t attr_bits; ///< attribute bits 242 | void *cb_mem; ///< memory for control block 243 | uint32_t cb_size; ///< size of provided memory for control block 244 | } osEventFlagsAttr_t; 245 | 246 | /// Attributes structure for mutex. 247 | typedef struct { 248 | const char *name; ///< name of the mutex 249 | uint32_t attr_bits; ///< attribute bits 250 | void *cb_mem; ///< memory for control block 251 | uint32_t cb_size; ///< size of provided memory for control block 252 | } osMutexAttr_t; 253 | 254 | /// Attributes structure for semaphore. 255 | typedef struct { 256 | const char *name; ///< name of the semaphore 257 | uint32_t attr_bits; ///< attribute bits 258 | void *cb_mem; ///< memory for control block 259 | uint32_t cb_size; ///< size of provided memory for control block 260 | } osSemaphoreAttr_t; 261 | 262 | /// Attributes structure for memory pool. 263 | typedef struct { 264 | const char *name; ///< name of the memory pool 265 | uint32_t attr_bits; ///< attribute bits 266 | void *cb_mem; ///< memory for control block 267 | uint32_t cb_size; ///< size of provided memory for control block 268 | void *mp_mem; ///< memory for data storage 269 | uint32_t mp_size; ///< size of provided memory for data storage 270 | } osMemoryPoolAttr_t; 271 | 272 | /// Attributes structure for message queue. 273 | typedef struct { 274 | const char *name; ///< name of the message queue 275 | uint32_t attr_bits; ///< attribute bits 276 | void *cb_mem; ///< memory for control block 277 | uint32_t cb_size; ///< size of provided memory for control block 278 | void *mq_mem; ///< memory for data storage 279 | uint32_t mq_size; ///< size of provided memory for data storage 280 | } osMessageQueueAttr_t; 281 | 282 | 283 | // ==== Kernel Management Functions ==== 284 | 285 | /// Initialize the RTOS Kernel. 286 | /// \return status code that indicates the execution status of the function. 287 | osStatus_t osKernelInitialize (void); 288 | 289 | /// Get RTOS Kernel Information. 290 | /// \param[out] version pointer to buffer for retrieving version information. 291 | /// \param[out] id_buf pointer to buffer for retrieving kernel identification string. 292 | /// \param[in] id_size size of buffer for kernel identification string. 293 | /// \return status code that indicates the execution status of the function. 294 | osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size); 295 | 296 | /// Get the current RTOS Kernel state. 297 | /// \return current RTOS Kernel state. 298 | osKernelState_t osKernelGetState (void); 299 | 300 | /// Start the RTOS Kernel scheduler. 301 | /// \return status code that indicates the execution status of the function. 302 | osStatus_t osKernelStart (void); 303 | 304 | /// Lock the RTOS Kernel scheduler. 305 | /// \return previous lock state (1 - locked, 0 - not locked, error code if negative). 306 | int32_t osKernelLock (void); 307 | 308 | /// Unlock the RTOS Kernel scheduler. 309 | /// \return previous lock state (1 - locked, 0 - not locked, error code if negative). 310 | int32_t osKernelUnlock (void); 311 | 312 | /// Restore the RTOS Kernel scheduler lock state. 313 | /// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock. 314 | /// \return new lock state (1 - locked, 0 - not locked, error code if negative). 315 | int32_t osKernelRestoreLock (int32_t lock); 316 | 317 | /// Suspend the RTOS Kernel scheduler. 318 | /// \return time in ticks, for how long the system can sleep or power-down. 319 | uint32_t osKernelSuspend (void); 320 | 321 | /// Resume the RTOS Kernel scheduler. 322 | /// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode. 323 | void osKernelResume (uint32_t sleep_ticks); 324 | 325 | /// Get the RTOS kernel tick count. 326 | /// \return RTOS kernel current tick count. 327 | uint32_t osKernelGetTickCount (void); 328 | 329 | /// Get the RTOS kernel tick frequency. 330 | /// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second. 331 | uint32_t osKernelGetTickFreq (void); 332 | 333 | /// Get the RTOS kernel system timer count. 334 | /// \return RTOS kernel current system timer count as 32-bit value. 335 | uint32_t osKernelGetSysTimerCount (void); 336 | 337 | /// Get the RTOS kernel system timer frequency. 338 | /// \return frequency of the system timer in hertz, i.e. timer ticks per second. 339 | uint32_t osKernelGetSysTimerFreq (void); 340 | 341 | 342 | // ==== Thread Management Functions ==== 343 | 344 | /// Create a thread and add it to Active Threads. 345 | /// \param[in] func thread function. 346 | /// \param[in] argument pointer that is passed to the thread function as start argument. 347 | /// \param[in] attr thread attributes; NULL: default values. 348 | /// \return thread ID for reference by other functions or NULL in case of error. 349 | osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); 350 | 351 | /// Get name of a thread. 352 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 353 | /// \return name as NULL terminated string. 354 | const char *osThreadGetName (osThreadId_t thread_id); 355 | 356 | /// Return the thread ID of the current running thread. 357 | /// \return thread ID for reference by other functions or NULL in case of error. 358 | osThreadId_t osThreadGetId (void); 359 | 360 | /// Get current thread state of a thread. 361 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 362 | /// \return current thread state of the specified thread. 363 | osThreadState_t osThreadGetState (osThreadId_t thread_id); 364 | 365 | /// Get stack size of a thread. 366 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 367 | /// \return stack size in bytes. 368 | uint32_t osThreadGetStackSize (osThreadId_t thread_id); 369 | 370 | /// Get available stack space of a thread based on stack watermark recording during execution. 371 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 372 | /// \return remaining stack space in bytes. 373 | uint32_t osThreadGetStackSpace (osThreadId_t thread_id); 374 | 375 | /// Change priority of a thread. 376 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 377 | /// \param[in] priority new priority value for the thread function. 378 | /// \return status code that indicates the execution status of the function. 379 | osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority); 380 | 381 | /// Get current priority of a thread. 382 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 383 | /// \return current priority value of the specified thread. 384 | osPriority_t osThreadGetPriority (osThreadId_t thread_id); 385 | 386 | /// Pass control to next thread that is in state \b READY. 387 | /// \return status code that indicates the execution status of the function. 388 | osStatus_t osThreadYield (void); 389 | 390 | /// Suspend execution of a thread. 391 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 392 | /// \return status code that indicates the execution status of the function. 393 | osStatus_t osThreadSuspend (osThreadId_t thread_id); 394 | 395 | /// Resume execution of a thread. 396 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 397 | /// \return status code that indicates the execution status of the function. 398 | osStatus_t osThreadResume (osThreadId_t thread_id); 399 | 400 | /// Detach a thread (thread storage can be reclaimed when thread terminates). 401 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 402 | /// \return status code that indicates the execution status of the function. 403 | osStatus_t osThreadDetach (osThreadId_t thread_id); 404 | 405 | /// Wait for specified thread to terminate. 406 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 407 | /// \return status code that indicates the execution status of the function. 408 | osStatus_t osThreadJoin (osThreadId_t thread_id); 409 | 410 | /// Terminate execution of current running thread. 411 | __NO_RETURN void osThreadExit (void); 412 | 413 | /// Terminate execution of a thread. 414 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 415 | /// \return status code that indicates the execution status of the function. 416 | osStatus_t osThreadTerminate (osThreadId_t thread_id); 417 | 418 | /// Get number of active threads. 419 | /// \return number of active threads. 420 | uint32_t osThreadGetCount (void); 421 | 422 | /// Enumerate active threads. 423 | /// \param[out] thread_array pointer to array for retrieving thread IDs. 424 | /// \param[in] array_items maximum number of items in array for retrieving thread IDs. 425 | /// \return number of enumerated threads. 426 | uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items); 427 | 428 | 429 | // ==== Thread Flags Functions ==== 430 | 431 | /// Set the specified Thread Flags of a thread. 432 | /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. 433 | /// \param[in] flags specifies the flags of the thread that shall be set. 434 | /// \return thread flags after setting or error code if highest bit set. 435 | uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags); 436 | 437 | /// Clear the specified Thread Flags of current running thread. 438 | /// \param[in] flags specifies the flags of the thread that shall be cleared. 439 | /// \return thread flags before clearing or error code if highest bit set. 440 | uint32_t osThreadFlagsClear (uint32_t flags); 441 | 442 | /// Get the current Thread Flags of current running thread. 443 | /// \return current thread flags. 444 | uint32_t osThreadFlagsGet (void); 445 | 446 | /// Wait for one or more Thread Flags of the current running thread to become signaled. 447 | /// \param[in] flags specifies the flags to wait for. 448 | /// \param[in] options specifies flags options (osFlagsXxxx). 449 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 450 | /// \return thread flags before clearing or error code if highest bit set. 451 | uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout); 452 | 453 | 454 | // ==== Generic Wait Functions ==== 455 | 456 | /// Wait for Timeout (Time Delay). 457 | /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value 458 | /// \return status code that indicates the execution status of the function. 459 | osStatus_t osDelay (uint32_t ticks); 460 | 461 | /// Wait until specified time. 462 | /// \param[in] ticks absolute time in ticks 463 | /// \return status code that indicates the execution status of the function. 464 | osStatus_t osDelayUntil (uint32_t ticks); 465 | 466 | 467 | // ==== Timer Management Functions ==== 468 | 469 | /// Create and Initialize a timer. 470 | /// \param[in] func function pointer to callback function. 471 | /// \param[in] type \ref osTimerOnce for one-shot or \ref osTimerPeriodic for periodic behavior. 472 | /// \param[in] argument argument to the timer callback function. 473 | /// \param[in] attr timer attributes; NULL: default values. 474 | /// \return timer ID for reference by other functions or NULL in case of error. 475 | osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr); 476 | 477 | /// Get name of a timer. 478 | /// \param[in] timer_id timer ID obtained by \ref osTimerNew. 479 | /// \return name as NULL terminated string. 480 | const char *osTimerGetName (osTimerId_t timer_id); 481 | 482 | /// Start or restart a timer. 483 | /// \param[in] timer_id timer ID obtained by \ref osTimerNew. 484 | /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer. 485 | /// \return status code that indicates the execution status of the function. 486 | osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks); 487 | 488 | /// Stop a timer. 489 | /// \param[in] timer_id timer ID obtained by \ref osTimerNew. 490 | /// \return status code that indicates the execution status of the function. 491 | osStatus_t osTimerStop (osTimerId_t timer_id); 492 | 493 | /// Check if a timer is running. 494 | /// \param[in] timer_id timer ID obtained by \ref osTimerNew. 495 | /// \return 0 not running, 1 running. 496 | uint32_t osTimerIsRunning (osTimerId_t timer_id); 497 | 498 | /// Delete a timer. 499 | /// \param[in] timer_id timer ID obtained by \ref osTimerNew. 500 | /// \return status code that indicates the execution status of the function. 501 | osStatus_t osTimerDelete (osTimerId_t timer_id); 502 | 503 | 504 | // ==== Event Flags Management Functions ==== 505 | 506 | /// Create and Initialize an Event Flags object. 507 | /// \param[in] attr event flags attributes; NULL: default values. 508 | /// \return event flags ID for reference by other functions or NULL in case of error. 509 | osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr); 510 | 511 | /// Get name of an Event Flags object. 512 | /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. 513 | /// \return name as NULL terminated string. 514 | const char *osEventFlagsGetName (osEventFlagsId_t ef_id); 515 | 516 | /// Set the specified Event Flags. 517 | /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. 518 | /// \param[in] flags specifies the flags that shall be set. 519 | /// \return event flags after setting or error code if highest bit set. 520 | uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags); 521 | 522 | /// Clear the specified Event Flags. 523 | /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. 524 | /// \param[in] flags specifies the flags that shall be cleared. 525 | /// \return event flags before clearing or error code if highest bit set. 526 | uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags); 527 | 528 | /// Get the current Event Flags. 529 | /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. 530 | /// \return current event flags. 531 | uint32_t osEventFlagsGet (osEventFlagsId_t ef_id); 532 | 533 | /// Wait for one or more Event Flags to become signaled. 534 | /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. 535 | /// \param[in] flags specifies the flags to wait for. 536 | /// \param[in] options specifies flags options (osFlagsXxxx). 537 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 538 | /// \return event flags before clearing or error code if highest bit set. 539 | uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout); 540 | 541 | /// Delete an Event Flags object. 542 | /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. 543 | /// \return status code that indicates the execution status of the function. 544 | osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id); 545 | 546 | 547 | // ==== Mutex Management Functions ==== 548 | 549 | /// Create and Initialize a Mutex object. 550 | /// \param[in] attr mutex attributes; NULL: default values. 551 | /// \return mutex ID for reference by other functions or NULL in case of error. 552 | osMutexId_t osMutexNew (const osMutexAttr_t *attr); 553 | 554 | /// Get name of a Mutex object. 555 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. 556 | /// \return name as NULL terminated string. 557 | const char *osMutexGetName (osMutexId_t mutex_id); 558 | 559 | /// Acquire a Mutex or timeout if it is locked. 560 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. 561 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 562 | /// \return status code that indicates the execution status of the function. 563 | osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout); 564 | 565 | /// Release a Mutex that was acquired by \ref osMutexAcquire. 566 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. 567 | /// \return status code that indicates the execution status of the function. 568 | osStatus_t osMutexRelease (osMutexId_t mutex_id); 569 | 570 | /// Get Thread which owns a Mutex object. 571 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. 572 | /// \return thread ID of owner thread or NULL when mutex was not acquired. 573 | osThreadId_t osMutexGetOwner (osMutexId_t mutex_id); 574 | 575 | /// Delete a Mutex object. 576 | /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. 577 | /// \return status code that indicates the execution status of the function. 578 | osStatus_t osMutexDelete (osMutexId_t mutex_id); 579 | 580 | 581 | // ==== Semaphore Management Functions ==== 582 | 583 | /// Create and Initialize a Semaphore object. 584 | /// \param[in] max_count maximum number of available tokens. 585 | /// \param[in] initial_count initial number of available tokens. 586 | /// \param[in] attr semaphore attributes; NULL: default values. 587 | /// \return semaphore ID for reference by other functions or NULL in case of error. 588 | osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr); 589 | 590 | /// Get name of a Semaphore object. 591 | /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. 592 | /// \return name as NULL terminated string. 593 | const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id); 594 | 595 | /// Acquire a Semaphore token or timeout if no tokens are available. 596 | /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. 597 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 598 | /// \return status code that indicates the execution status of the function. 599 | osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout); 600 | 601 | /// Release a Semaphore token up to the initial maximum count. 602 | /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. 603 | /// \return status code that indicates the execution status of the function. 604 | osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id); 605 | 606 | /// Get current Semaphore token count. 607 | /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. 608 | /// \return number of tokens available. 609 | uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id); 610 | 611 | /// Delete a Semaphore object. 612 | /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. 613 | /// \return status code that indicates the execution status of the function. 614 | osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id); 615 | 616 | 617 | // ==== Memory Pool Management Functions ==== 618 | 619 | /// Create and Initialize a Memory Pool object. 620 | /// \param[in] block_count maximum number of memory blocks in memory pool. 621 | /// \param[in] block_size memory block size in bytes. 622 | /// \param[in] attr memory pool attributes; NULL: default values. 623 | /// \return memory pool ID for reference by other functions or NULL in case of error. 624 | osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr); 625 | 626 | /// Get name of a Memory Pool object. 627 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 628 | /// \return name as NULL terminated string. 629 | const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id); 630 | 631 | /// Allocate a memory block from a Memory Pool. 632 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 633 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 634 | /// \return address of the allocated memory block or NULL in case of no memory is available. 635 | void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout); 636 | 637 | /// Return an allocated memory block back to a Memory Pool. 638 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 639 | /// \param[in] block address of the allocated memory block to be returned to the memory pool. 640 | /// \return status code that indicates the execution status of the function. 641 | osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block); 642 | 643 | /// Get maximum number of memory blocks in a Memory Pool. 644 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 645 | /// \return maximum number of memory blocks. 646 | uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id); 647 | 648 | /// Get memory block size in a Memory Pool. 649 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 650 | /// \return memory block size in bytes. 651 | uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id); 652 | 653 | /// Get number of memory blocks used in a Memory Pool. 654 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 655 | /// \return number of memory blocks used. 656 | uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id); 657 | 658 | /// Get number of memory blocks available in a Memory Pool. 659 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 660 | /// \return number of memory blocks available. 661 | uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id); 662 | 663 | /// Delete a Memory Pool object. 664 | /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. 665 | /// \return status code that indicates the execution status of the function. 666 | osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id); 667 | 668 | 669 | // ==== Message Queue Management Functions ==== 670 | 671 | /// Create and Initialize a Message Queue object. 672 | /// \param[in] msg_count maximum number of messages in queue. 673 | /// \param[in] msg_size maximum message size in bytes. 674 | /// \param[in] attr message queue attributes; NULL: default values. 675 | /// \return message queue ID for reference by other functions or NULL in case of error. 676 | osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); 677 | 678 | /// Get name of a Message Queue object. 679 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 680 | /// \return name as NULL terminated string. 681 | const char *osMessageQueueGetName (osMessageQueueId_t mq_id); 682 | 683 | /// Put a Message into a Queue or timeout if Queue is full. 684 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 685 | /// \param[in] msg_ptr pointer to buffer with message to put into a queue. 686 | /// \param[in] msg_prio message priority. 687 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 688 | /// \return status code that indicates the execution status of the function. 689 | osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout); 690 | 691 | /// Get a Message from a Queue or timeout if Queue is empty. 692 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 693 | /// \param[out] msg_ptr pointer to buffer for message to get from a queue. 694 | /// \param[out] msg_prio pointer to buffer for message priority or NULL. 695 | /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. 696 | /// \return status code that indicates the execution status of the function. 697 | osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout); 698 | 699 | /// Get maximum number of messages in a Message Queue. 700 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 701 | /// \return maximum number of messages. 702 | uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id); 703 | 704 | /// Get maximum message size in a Memory Pool. 705 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 706 | /// \return maximum message size in bytes. 707 | uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id); 708 | 709 | /// Get number of queued messages in a Message Queue. 710 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 711 | /// \return number of queued messages. 712 | uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id); 713 | 714 | /// Get number of available slots for messages in a Message Queue. 715 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 716 | /// \return number of available slots for messages. 717 | uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id); 718 | 719 | /// Reset a Message Queue to initial empty state. 720 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 721 | /// \return status code that indicates the execution status of the function. 722 | osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id); 723 | 724 | /// Delete a Message Queue object. 725 | /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. 726 | /// \return status code that indicates the execution status of the function. 727 | osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id); 728 | 729 | 730 | #ifdef __cplusplus 731 | } 732 | #endif 733 | 734 | #endif // CMSIS_OS2_H_ 735 | -------------------------------------------------------------------------------- /cmsis-esp32/include/lwip.h: -------------------------------------------------------------------------------- 1 | #ifndef _LWIP_H_ 2 | #define _LWIP_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | extern void MX_LWIP_Init(void); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif /* _LWIP_H_ */ -------------------------------------------------------------------------------- /cmsis-esp32/lwip.c: -------------------------------------------------------------------------------- 1 | #include "lwip.h" 2 | #include "lwipopts.h" 3 | #include "cmsis_os.h" 4 | #include "freertos/FreeRTOS.h" 5 | #include "freertos/semphr.h" 6 | #include 7 | 8 | static SemaphoreHandle_t xMutex = NULL; 9 | 10 | void MX_LWIP_Init(void) 11 | { 12 | xMutex = xSemaphoreCreateMutex(); 13 | return; 14 | } 15 | 16 | void sys_lock_tcpip_core(void) 17 | { 18 | xSemaphoreTake(xMutex, portMAX_DELAY); 19 | return; 20 | } 21 | 22 | void sys_unlock_tcpip_core(void) 23 | { 24 | xSemaphoreGive(xMutex); 25 | return; 26 | } 27 | -------------------------------------------------------------------------------- /dev_tool/README.md: -------------------------------------------------------------------------------- 1 | # mros2-esp32 dev-tool 2 | 3 | Building mros2-esp32 tool using docker. 4 | 5 | 6 | 7 | 8 | ## Requirements 9 | 10 | - USB accessable docker-compose environment 11 | 12 | 13 | 14 | ## Usage 15 | 16 | M5Stack CoreS3 17 | 18 | ```bash 19 | bash build_example.bash /dev/ttyACM0 ../../mros2-esp32 ../workspace/echoback_string esp32s3 20 | ``` 21 | 22 | 23 | ### Arguments 24 | 25 | - 1: Serial port (default: `/dev/ttyUSB0`) 26 | - 2: Path to mros2-esp32 (default: `../../mros2-esp32`) 27 | - 3: Path to workspace (default: `../workspace/echoback_string`) 28 | - 4: Target board (esp32, esp32s2, esp32s3...) (default: `esp32`) 29 | -------------------------------------------------------------------------------- /dev_tool/build_example.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR=$(cd $(dirname $0); pwd) 3 | PORT=${1:-/dev/ttyUSB0} 4 | MROS2_DIR=${2:-${SCRIPT_DIR}/../../mros2-esp32} 5 | WORKSPACE=${3:-${SCRIPT_DIR}/../workspace/echoback_string} 6 | TARGET=${4:-esp32} 7 | 8 | echo "=====================" 9 | echo "PORT: ${PORT}" 10 | echo "MROS2_DIR: ${MROS2_DIR}" 11 | echo "WORKSPACE: ${WORKSPACE}" 12 | echo "TARGET: ${TARGET}" 13 | echo "=====================" 14 | 15 | rm -rf ${SCRIPT_DIR}/.env 16 | echo "PORT=${PORT}" > ${SCRIPT_DIR}/.env 17 | echo "MROS2_DIR=${MROS2_DIR}" >> ${SCRIPT_DIR}/.env 18 | echo "WORKSPACE=${WORKSPACE}" >> ${SCRIPT_DIR}/.env 19 | echo "TARGET=${TARGET}" >> ${SCRIPT_DIR}/.env 20 | 21 | cd ${SCRIPT_DIR} 22 | 23 | if [ ! -d ${MROS2_DIR} ]; then 24 | echo "mros2-esp32 directory not found." 25 | fi 26 | 27 | docker-compose up --build mros2_esp32 28 | -------------------------------------------------------------------------------- /dev_tool/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | mros2_esp32: 4 | build: 5 | context: ./docker 6 | dockerfile: esp_idf.dockerfile 7 | container_name: esp_idf 8 | volumes: 9 | - ${MROS2_DIR}:/mros2-esp32 10 | - ${WORKSPACE}:/mros2-esp32/workspace/target 11 | devices: 12 | - ${PORT}:${PORT} 13 | environment: 14 | - PORT=${PORT} 15 | - TARGET=${TARGET} 16 | command: ["/tmp/build_mros2.bash"] 17 | env_file: 18 | - .env -------------------------------------------------------------------------------- /dev_tool/docker/build_mros2.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR=/mros2-esp32/workspace/target/ 3 | 4 | . /esp/esp-idf/export.sh 5 | 6 | cd ${SCRIPT_DIR} 7 | rm -rf ${SCRIPT_DIR}/build/ 8 | 9 | idf.py set-target ${TARGET} 10 | if [ $? -ne 0 ]; then 11 | echo "Failed to set target" 12 | exit 1 13 | fi 14 | 15 | sed -i 's/CONFIG_LWIP_IPV6=y/CONFIG_LWIP_IPV6=n/g' ${SCRIPT_DIR}/sdkconfig 16 | 17 | idf.py build 18 | idf.py -p ${PORT} flash 19 | if [ $? -ne 0 ]; then 20 | echo "Failed to flash" 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /dev_tool/docker/esp_idf.dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | ENV TZ=Asia/Tokyo 4 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | 7 | RUN apt update && apt install locales && \ 8 | locale-gen en_US en_US.UTF-8 && \ 9 | update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 && \ 10 | apt -y clean && \ 11 | rm -rf /var/lib/apt/lists/* 12 | ENV LANG=en_US.UTF-8 13 | 14 | RUN apt-get update && \ 15 | apt-get install -y \ 16 | git wget flex bison gperf python3 python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 17 | 18 | RUN mkdir -p /esp 19 | RUN cd /esp && git clone --recursive https://github.com/espressif/esp-idf.git -b v5.2-dev && \ 20 | cd /esp/esp-idf && \ 21 | ./install.sh all 22 | 23 | RUN /bin/bash -c "source /esp/esp-idf/export.sh && \ 24 | pip3 install jinja2" 25 | 26 | COPY ./build_mros2.bash /tmp/build_mros2.bash 27 | -------------------------------------------------------------------------------- /platform/mros2-platform.cpp: -------------------------------------------------------------------------------- 1 | /* target dependent procedure for mros2-mbed 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* NOTE: 18 | * this file has not been implemented and used yet 19 | */ 20 | 21 | #include "mros2.h" 22 | #include "mros2-platform.h" 23 | 24 | #include "cmsis_os.h" 25 | #include "wifi.h" 26 | 27 | 28 | /* 29 | * Setup network I/F 30 | */ 31 | extern "C" esp_err_t mros2_platform_network_connect(void) 32 | { 33 | init_wifi(); 34 | osKernelStart(); 35 | 36 | /* get mros2 IP address and set it to RTPS */ 37 | uint32_t ipaddr = get_mros2_ip_addr(); 38 | return mros2_setIPAddrRTPS(ipaddr); 39 | } 40 | -------------------------------------------------------------------------------- /platform/mros2-platform.h: -------------------------------------------------------------------------------- 1 | #ifndef MROS2_PLATFORM_H 2 | #define MROS2_PLATFORM_H 3 | 4 | #define MROS2_PLATFORM_NAME "mros2-esp32" 5 | #define TARGET_NAME "ESP32" 6 | 7 | #include "cmsis_os.h" 8 | #include "wifi.h" 9 | 10 | /* convert TARGET_NAME to put into message */ 11 | #define quote(x) std::string(q(x)) 12 | #define q(x) #x 13 | 14 | 15 | /* NOTE: this function has not been implemented and used yet */ 16 | extern "C" esp_err_t mros2_platform_network_connect(void); 17 | 18 | 19 | #endif /* MROS2_PLATFORM_H */ -------------------------------------------------------------------------------- /platform/rtps/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License 3 | Copyright (c) 2019 Lehrstuhl Informatik 11 - RWTH Aachen University 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | THE SOFTWARE 19 | 20 | This file is part of embeddedRTPS. 21 | 22 | Author: i11 - Embedded Software, RWTH Aachen University 23 | */ 24 | 25 | #ifndef RTPS_CONFIG_H 26 | #define RTPS_CONFIG_H 27 | 28 | #include "rtps/common/types.h" 29 | 30 | namespace rtps 31 | { 32 | 33 | #define IS_LITTLE_ENDIAN 1 34 | 35 | // define only if using FreeRTOS 36 | #define OS_IS_FREERTOS 37 | 38 | namespace Config 39 | { 40 | const VendorId_t VENDOR_ID = {13, 37}; 41 | /* setting IP address for RTPS was moved to mros2-/target/mros2_target.cpp */ 42 | //const std::array IP_ADDRESS = { 43 | // 192, 168, 11, 107 44 | //}; // Needs to be set in lwipcfg.h too. 45 | extern std::array IP_ADDRESS; 46 | const GuidPrefix_t BASE_GUID_PREFIX{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12}; 47 | 48 | const uint8_t DOMAIN_ID = 0; // 230 possible with UDP 49 | const uint8_t NUM_STATELESS_WRITERS = 4; 50 | const uint8_t NUM_STATELESS_READERS = 4; 51 | const uint8_t NUM_STATEFUL_READERS = 8; 52 | const uint8_t NUM_STATEFUL_WRITERS = 8; 53 | const uint8_t MAX_NUM_PARTICIPANTS = 1; 54 | const uint8_t NUM_WRITERS_PER_PARTICIPANT = 16; 55 | const uint8_t NUM_READERS_PER_PARTICIPANT = 16; 56 | const uint8_t NUM_WRITER_PROXIES_PER_READER = 6; 57 | const uint8_t NUM_READER_PROXIES_PER_WRITER = 6; 58 | 59 | const uint8_t MAX_NUM_UNMATCHED_REMOTE_WRITERS = 15; 60 | const uint8_t MAX_NUM_UNMATCHED_REMOTE_READERS = 15; 61 | 62 | const uint8_t MAX_NUM_READER_CALLBACKS = 5; 63 | 64 | const uint8_t HISTORY_SIZE_STATELESS = 2; 65 | const uint8_t HISTORY_SIZE_STATEFUL = 10; 66 | 67 | const uint8_t MAX_TYPENAME_LENGTH = 40; 68 | const uint8_t MAX_TOPICNAME_LENGTH = 40; 69 | 70 | const int HEARTBEAT_STACKSIZE = 4096; // byte 71 | const int THREAD_POOL_WRITER_STACKSIZE = 4096; // byte 72 | const int THREAD_POOL_READER_STACKSIZE = 4096; // byte 73 | const uint16_t SPDP_WRITER_STACKSIZE = 4096; // byte 74 | 75 | const uint16_t SF_WRITER_HB_PERIOD_MS = 4000; 76 | const uint16_t SPDP_RESEND_PERIOD_MS = 1000; 77 | const uint8_t SPDP_CYCLECOUNT_HEARTBEAT = 78 | 2; // skip x SPDP rounds before checking liveliness 79 | const uint8_t SPDP_WRITER_PRIO = 24; 80 | const uint8_t SPDP_MAX_NUMBER_FOUND_PARTICIPANTS = 5; 81 | const uint8_t SPDP_MAX_NUM_LOCATORS = 5; 82 | const Duration_t SPDP_DEFAULT_REMOTE_LEASE_DURATION = { 83 | 100, 0 84 | }; // Default lease duration for remote participants, usually 85 | // overwritten by remote info 86 | const Duration_t SPDP_MAX_REMOTE_LEASE_DURATION = { 87 | 180, 88 | 0 89 | }; // Absolute maximum lease duration, ignoring remote participant info 90 | 91 | const Duration_t SPDP_LEASE_DURATION = {100, 0}; 92 | 93 | const int MAX_NUM_UDP_CONNECTIONS = 10; 94 | 95 | const int THREAD_POOL_NUM_WRITERS = 1; 96 | const int THREAD_POOL_NUM_READERS = 1; 97 | const int THREAD_POOL_WRITER_PRIO = 24; 98 | const int THREAD_POOL_READER_PRIO = 24; 99 | const int THREAD_POOL_WORKLOAD_QUEUE_LENGTH = 20; 100 | 101 | constexpr int OVERALL_HEAP_SIZE = 102 | THREAD_POOL_NUM_WRITERS * THREAD_POOL_WRITER_STACKSIZE + 103 | THREAD_POOL_NUM_READERS * THREAD_POOL_READER_STACKSIZE + 104 | MAX_NUM_PARTICIPANTS * SPDP_WRITER_STACKSIZE + 105 | NUM_STATEFUL_WRITERS * HEARTBEAT_STACKSIZE; 106 | } // namespace Config 107 | } // namespace rtps 108 | 109 | #endif // RTPS_CONFIG_H 110 | -------------------------------------------------------------------------------- /platform/wifi/wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * NOTE: 3 | * This file is copied from esp-idf examples as the below, and modified for usage of mros2-esp32. 4 | * https://github.com/espressif/esp-idf/blob/master/examples/wifi/getting_started/station/main/station_example_main.c 5 | * Therefore, mROS-base org inherits the Public Domain (or CC0) LICENCE for this file from the original file. 6 | */ 7 | 8 | #include "wifi.h" 9 | 10 | #include "freertos/FreeRTOS.h" 11 | #include "freertos/task.h" 12 | #include "freertos/event_groups.h" 13 | #include "esp_system.h" 14 | #include "esp_wifi.h" 15 | #include "esp_log.h" 16 | #include "nvs_flash.h" 17 | 18 | #include "lwip/err.h" 19 | #include "lwip/ip_addr.h" 20 | 21 | static EventGroupHandle_t s_wifi_event_group; 22 | static const char *TAG = "wifi station"; 23 | static int s_retry_num = 0; 24 | 25 | /* keep IP address obtained in event_handler */ 26 | static uint32_t mros2_ip_addr; 27 | 28 | static void event_handler(void *arg, esp_event_base_t event_base, 29 | int32_t event_id, void *event_data) 30 | { 31 | if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) 32 | { 33 | esp_wifi_connect(); 34 | } 35 | #ifdef STATIC_IP 36 | else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) 37 | { 38 | esp_netif_t *netif = (esp_netif_t *)arg; 39 | if (esp_netif_dhcpc_stop(netif) != ESP_OK) 40 | { 41 | ESP_LOGE(TAG, "Failed to stop dhcp client"); 42 | return; 43 | } 44 | esp_netif_ip_info_t ip; 45 | memset(&ip, 0, sizeof(esp_netif_ip_info_t)); 46 | ip.ip.addr = ipaddr_addr(NETIF_IPADDR); 47 | ip.netmask.addr = ipaddr_addr(NETIF_NETMASK); 48 | ip.gw.addr = ipaddr_addr(NETIF_GW); 49 | if (esp_netif_set_ip_info(netif, &ip) != ESP_OK) 50 | { 51 | ESP_LOGE(TAG, "Failed to set ip info"); 52 | return; 53 | } 54 | } 55 | #endif 56 | else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) 57 | { 58 | if (s_retry_num < ESP_MAXIMUM_RETRY) 59 | { 60 | esp_wifi_connect(); 61 | s_retry_num++; 62 | ESP_LOGI(TAG, "retry to connect to the AP"); 63 | } 64 | else 65 | { 66 | xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); 67 | } 68 | ESP_LOGI(TAG, "connect to the AP fail"); 69 | } 70 | else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) 71 | { 72 | ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; 73 | ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); 74 | s_retry_num = 0; 75 | xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); 76 | 77 | /* keep IP address obtained in event_handler */ 78 | mros2_ip_addr = event->ip_info.ip.addr; 79 | } 80 | } 81 | 82 | void wifi_init_sta(void) 83 | { 84 | s_wifi_event_group = xEventGroupCreate(); 85 | 86 | ESP_ERROR_CHECK(esp_netif_init()); 87 | 88 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 89 | esp_netif_create_default_wifi_sta(); 90 | 91 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 92 | ESP_ERROR_CHECK(esp_wifi_init(&cfg)); 93 | 94 | esp_event_handler_instance_t instance_any_id; 95 | esp_event_handler_instance_t instance_got_ip; 96 | ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, 97 | ESP_EVENT_ANY_ID, 98 | &event_handler, 99 | NULL, 100 | &instance_any_id)); 101 | ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, 102 | IP_EVENT_STA_GOT_IP, 103 | &event_handler, 104 | NULL, 105 | &instance_got_ip)); 106 | 107 | wifi_config_t wifi_config = { 108 | .sta = { 109 | .ssid = ESP_WIFI_SSID, 110 | .password = ESP_WIFI_PASS, 111 | .threshold = {.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD}, 112 | .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, 113 | }, 114 | }; 115 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); 116 | ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); 117 | ESP_ERROR_CHECK(esp_wifi_start()); 118 | 119 | ESP_LOGI(TAG, "wifi_init_sta finished."); 120 | 121 | /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum 122 | * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */ 123 | EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, 124 | WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, 125 | pdFALSE, 126 | pdFALSE, 127 | portMAX_DELAY); 128 | 129 | /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually 130 | * happened. */ 131 | if (bits & WIFI_CONNECTED_BIT) 132 | { 133 | ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", 134 | ESP_WIFI_SSID, ESP_WIFI_PASS); 135 | } 136 | else if (bits & WIFI_FAIL_BIT) 137 | { 138 | ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", 139 | ESP_WIFI_SSID, ESP_WIFI_PASS); 140 | } 141 | else 142 | { 143 | ESP_LOGE(TAG, "UNEXPECTED EVENT"); 144 | } 145 | } 146 | 147 | void init_wifi(void) 148 | { 149 | esp_err_t ret = nvs_flash_init(); 150 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) 151 | { 152 | ESP_ERROR_CHECK(nvs_flash_erase()); 153 | ret = nvs_flash_init(); 154 | } 155 | ESP_ERROR_CHECK(ret); 156 | 157 | ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); 158 | wifi_init_sta(); 159 | } 160 | 161 | uint32_t get_mros2_ip_addr(void) 162 | { 163 | return mros2_ip_addr; 164 | } -------------------------------------------------------------------------------- /platform/wifi/wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NOTE: 3 | * This file is copied from esp-idf examples as the below, and modified for usage of mros2-esp32. 4 | * https://github.com/espressif/esp-idf/blob/master/examples/wifi/getting_started/station/main/station_example_main.c 5 | * Therefore, mROS-base org inherits the Public Domain (or CC0) LICENCE for this file from the original file. 6 | */ 7 | 8 | #include "esp_wifi_types.h" 9 | 10 | #define ESP_WIFI_SSID "SSID" 11 | #define ESP_WIFI_PASS "PASS" 12 | #define ESP_MAXIMUM_RETRY 3 13 | #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK 14 | 15 | #define WIFI_CONNECTED_BIT BIT0 16 | #define WIFI_FAIL_BIT BIT1 17 | 18 | /* 19 | * Caution: 20 | * We have not tested the operation using STATIC_IP setting yet. 21 | * So you may not un-comment the below line to use DHCP setting 22 | */ 23 | // #define STATIC_IP 24 | #ifdef STATIC_IP 25 | #define NETIF_IPADDR "192.168.11.107" 26 | #define NETIF_NETMASK "255.255.255.0" 27 | #define NETIF_GW "192.168.11.1" 28 | #endif 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | extern void init_wifi(void); 33 | uint32_t get_mros2_ip_addr(void); 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /workspace/echoback_string/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(echoback_string) 10 | -------------------------------------------------------------------------------- /workspace/echoback_string/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "echoback_string.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/echoback_string/main/echoback_string.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "std_msgs/msg/string.hpp" 20 | 21 | 22 | void userCallback(std_msgs::msg::String *msg) 23 | { 24 | MROS2_INFO("subscribed msg: '%s'", msg->data.c_str()); 25 | } 26 | 27 | extern "C" void app_main(void) 28 | { 29 | /* connect to the network */ 30 | if (mros2_platform_network_connect()) 31 | { 32 | MROS2_INFO("successfully connect and setup network\r\n---"); 33 | } 34 | else 35 | { 36 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 37 | return; 38 | } 39 | 40 | MROS2_INFO("%s start!", MROS2_PLATFORM_NAME); 41 | MROS2_INFO("app name: echoback_string"); 42 | 43 | mros2::init(0, NULL); 44 | MROS2_DEBUG("mROS 2 initialization is completed"); 45 | 46 | mros2::Node node = mros2::Node::create_node("mros2_node"); 47 | mros2::Publisher pub = node.create_publisher("to_linux", 10); 48 | mros2::Subscriber sub = node.create_subscription("to_stm", 10, userCallback); 49 | 50 | osDelay(100); 51 | MROS2_INFO("ready to pub/sub message\r\n---"); 52 | 53 | auto count = 0; 54 | while (1) 55 | { 56 | auto msg = std_msgs::msg::String(); 57 | msg.data = "Hello from " + std::string(MROS2_PLATFORM_NAME) + " onto " + quote(TARGET_NAME) + ": " + std::to_string(count++); 58 | MROS2_INFO("publishing msg: '%s'", msg.data.c_str()); 59 | pub.publish(msg); 60 | osDelay(1000); 61 | } 62 | 63 | mros2::spin(); 64 | return; 65 | } -------------------------------------------------------------------------------- /workspace/echoreply_string/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(echoreply_string) -------------------------------------------------------------------------------- /workspace/echoreply_string/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "echoreply_string.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/echoreply_string/main/echoreply_string.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "std_msgs/msg/string.hpp" 20 | 21 | mros2::Subscriber sub; 22 | mros2::Publisher pub; 23 | 24 | 25 | void userCallback(std_msgs::msg::String *msg) 26 | { 27 | MROS2_INFO("subscribed msg: '%s'", msg->data.c_str()); 28 | MROS2_INFO("publishing msg: '%s'", msg->data.c_str()); 29 | pub.publish(*msg); 30 | } 31 | 32 | extern "C" void app_main(void) 33 | { 34 | /* connect to the network */ 35 | if (mros2_platform_network_connect()) 36 | { 37 | MROS2_INFO("successfully connect and setup network\r\n---"); 38 | } 39 | else 40 | { 41 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 42 | return; 43 | } 44 | 45 | MROS2_INFO("mbed mros2 start!"); 46 | MROS2_INFO("app name: echoreply_string"); 47 | 48 | mros2::init(0, NULL); 49 | MROS2_DEBUG("mROS 2 initialization is completed"); 50 | 51 | mros2::Node node = mros2::Node::create_node("mros2_node"); 52 | pub = node.create_publisher("to_linux", 10); 53 | sub = node.create_subscription("to_stm", 10, userCallback); 54 | osDelay(100); 55 | MROS2_INFO("ready to pub/sub message\r\n---"); 56 | 57 | mros2::spin(); 58 | return; 59 | } -------------------------------------------------------------------------------- /workspace/m5stack_sample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(m5stack_sample) -------------------------------------------------------------------------------- /workspace/m5stack_sample/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mROS-base/mros2-esp32/28b6e63727f13b427d3fb29823ddce574a30d3e7/workspace/m5stack_sample/components/.gitkeep -------------------------------------------------------------------------------- /workspace/m5stack_sample/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "m5stack_sample.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32" "M5Unified") 4 | -------------------------------------------------------------------------------- /workspace/m5stack_sample/main/m5stack_sample.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "std_msgs/msg/string.hpp" 20 | 21 | #include "M5Unified.h" 22 | 23 | 24 | void userCallback(std_msgs::msg::String *msg) 25 | { 26 | MROS2_INFO("subscribed msg: '%s'", msg->data.c_str()); 27 | M5.Lcd.printf("subscribed msg: '%s'\r\n", msg->data.c_str()); 28 | } 29 | 30 | extern "C" void app_main(void) 31 | { 32 | /* connect to the network */ 33 | if (mros2_platform_network_connect()) 34 | { 35 | MROS2_INFO("successfully connect and setup network\r\n---"); 36 | } 37 | else 38 | { 39 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 40 | return; 41 | } 42 | 43 | MROS2_INFO("%s start!", MROS2_PLATFORM_NAME); 44 | MROS2_INFO("app name: echoback_string"); 45 | 46 | auto cfg = M5.config(); 47 | M5.begin(cfg); 48 | M5.Lcd.setTextSize(2); 49 | M5.Lcd.println(""); 50 | M5.Lcd.printf("%s start!\r\n", MROS2_PLATFORM_NAME); 51 | M5.Lcd.printf("app name: m5stack_sample\r\n"); 52 | 53 | mros2::init(0, NULL); 54 | MROS2_DEBUG("mROS 2 initialization is completed"); 55 | 56 | mros2::Node node = mros2::Node::create_node("mros2_node"); 57 | mros2::Publisher pub = node.create_publisher("to_linux", 10); 58 | mros2::Subscriber sub = node.create_subscription("to_stm", 10, userCallback); 59 | 60 | osDelay(100); 61 | MROS2_INFO("ready to pub/sub message\r\n---"); 62 | 63 | auto count = 0; 64 | while (1) 65 | { 66 | auto msg = std_msgs::msg::String(); 67 | msg.data = "Hello from mros2-mbed onto " + quote(TARGET_NAME) + ": " + std::to_string(count++); 68 | MROS2_INFO("publishing msg: '%s'", msg.data.c_str()); 69 | pub.publish(msg); 70 | M5.Lcd.printf("publishing msg: '%s'\r\n", msg.data.c_str()); 71 | osDelay(1000); 72 | } 73 | 74 | mros2::spin(); 75 | return; 76 | } -------------------------------------------------------------------------------- /workspace/pub_float32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(pub_float32) -------------------------------------------------------------------------------- /workspace/pub_float32/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "pub_float32.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/pub_float32/main/pub_float32.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "std_msgs/msg/float32.hpp" 20 | 21 | 22 | extern "C" void app_main(void) 23 | { 24 | /* connect to the network */ 25 | if (mros2_platform_network_connect()) 26 | { 27 | MROS2_INFO("successfully connect and setup network\r\n---"); 28 | } 29 | else 30 | { 31 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 32 | return; 33 | } 34 | 35 | MROS2_INFO("mbed mros2 start!"); 36 | MROS2_INFO("app name: pub_float32"); 37 | 38 | mros2::init(0, NULL); 39 | MROS2_DEBUG("mROS 2 initialization is completed"); 40 | 41 | mros2::Node node = mros2::Node::create_node("mros2_node"); 42 | mros2::Publisher pub = node.create_publisher("to_linux", 10); 43 | osDelay(100); 44 | MROS2_INFO("ready to pub/sub message\r\n---"); 45 | 46 | std_msgs::msg::Float32 msg; 47 | auto publish_count = -0.5; 48 | while (1) 49 | { 50 | msg.data = publish_count; 51 | MROS2_INFO("publishing float msg!!"); 52 | pub.publish(msg); 53 | 54 | if (0.0 >= msg.data) 55 | MROS2_INFO("msg <= 0.0"); 56 | else if (0.0 < msg.data && msg.data < 0.5) 57 | MROS2_INFO("0.0 < msg < 0.5"); 58 | else if (0.5 < msg.data && msg.data < 1.0) 59 | MROS2_INFO("0.5 < msg < 1.0"); 60 | else 61 | MROS2_INFO("msg >= 1.0"); 62 | 63 | publish_count = publish_count + 0.1; 64 | osDelay(1000); 65 | } 66 | 67 | mros2::spin(); 68 | return; 69 | } -------------------------------------------------------------------------------- /workspace/pub_image/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(pub_image) -------------------------------------------------------------------------------- /workspace/pub_image/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "pub_image.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/pub_image/main/mros_image.h: -------------------------------------------------------------------------------- 1 | #define MROS_IMAGE_HEIGHT 50 2 | #define MROS_IMAGE_WIDTH 50 3 | 4 | // array size is 7500 5 | static const unsigned char mros_image[] = { 6 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 8 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 9 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 10 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 11 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 12 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 13 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 14 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 15 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 16 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 17 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 18 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 19 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 20 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 21 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 22 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 23 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 24 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfa, 0xfa, 0xfb, 0xc2, 0xc5, 0xcd, 0xa4, 0xa9, 0xb4, 0xb8, 0xbc, 0xc4, 0xf3, 0xf4, 0xf5, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 25 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xcf, 0xd2, 0xd8, 0xa8, 0xad, 0xb8, 0xaf, 0xb4, 0xbe, 0xe7, 0xe8, 0xeb, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 26 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xe1, 0xe3, 0xe6, 0xad, 0xb1, 0xbb, 0xa9, 0xae, 0xb8, 0xd7, 0xd9, 0xde, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 27 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xe7, 0xe8, 0xeb, 0x4e, 0x59, 0x6e, 0x20, 0x2d, 0x49, 0x21, 0x2e, 0x49, 0x20, 0x2d, 0x49, 0x3c, 0x47, 0x5f, 0xd3, 0xd5, 0xda, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 28 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf7, 0xf8, 0xf9, 0x76, 0x7e, 0x8f, 0x22, 0x2f, 0x4b, 0x21, 0x2e, 0x49, 0x20, 0x2d, 0x49, 0x2c, 0x39, 0x53, 0xa9, 0xae, 0xb9, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 29 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x9e, 0xa3, 0xaf, 0x29, 0x36, 0x50, 0x20, 0x2e, 0x49, 0x21, 0x2e, 0x49, 0x25, 0x31, 0x4d, 0x80, 0x87, 0x97, 0xfb, 0xfb, 0xfb, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 30 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfa, 0xfb, 0xfb, 0x52, 0x5c, 0x71, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x25, 0x32, 0x4d, 0x35, 0x41, 0x5a, 0xee, 0xef, 0xf1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 31 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x80, 0x88, 0x98, 0x22, 0x2f, 0x4a, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x25, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0xcd, 0xd0, 0xd6, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 32 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xb4, 0xb8, 0xc1, 0x21, 0x2e, 0x4a, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x22, 0x2f, 0x4a, 0x92, 0x99, 0xa6, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 33 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xc7, 0xcb, 0xd2, 0x21, 0x2e, 0x49, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x21, 0x2e, 0x4a, 0x9d, 0xa3, 0xaf, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 34 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xec, 0xed, 0xef, 0x2d, 0x3a, 0x54, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x65, 0x6f, 0x81, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 35 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x4c, 0x57, 0x6d, 0x25, 0x32, 0x4d, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x25, 0x32, 0x4c, 0x39, 0x45, 0x5d, 0xf9, 0xf9, 0xfa, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 36 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x99, 0x9f, 0xab, 0x22, 0x2e, 0x4a, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x70, 0x78, 0x8a, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 37 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfe, 0xfe, 0xcc, 0xcf, 0xd5, 0x20, 0x2d, 0x49, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x25, 0x32, 0x4d, 0x40, 0x4c, 0x63, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 38 | 0xfe, 0xfe, 0xf6, 0xf7, 0xf8, 0x30, 0x3d, 0x56, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x27, 0x34, 0x4f, 0xe6, 0xe7, 0xea, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 39 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xab, 0xaf, 0xb9, 0x20, 0x2e, 0x49, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x23, 0x30, 0x4b, 0x80, 0x87, 0x97, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 40 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xd6, 0xd8, 0xdd, 0x22, 0x30, 0x4b, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x25, 0x32, 0x4d, 0x4a, 0x54, 0x6b, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 41 | 0xfe, 0xfe, 0xfc, 0xfc, 0xfc, 0x36, 0x43, 0x5b, 0x25, 0x32, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x2b, 0x37, 0x51, 0xed, 0xee, 0xf0, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 42 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xe8, 0xe9, 0xec, 0x2c, 0x38, 0x52, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x22, 0x30, 0x4b, 0xc7, 0xca, 0xd1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 43 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfc, 0xfc, 0xfc, 0x4a, 0x54, 0x6b, 0x25, 0x32, 0x4d, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x22, 0x2f, 0x4a, 0x97, 0x9d, 0xaa, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 44 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x7a, 0x82, 0x92, 0x23, 0x30, 0x4b, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x24, 0x31, 0x4c, 0x25, 0x32, 0x4d, 0x5a, 0x64, 0x78, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 45 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xa5, 0xaa, 0xb5, 0x22, 0x2f, 0x4a, 0x25, 0x32, 0x4d, 0x25, 0x32, 0x4c, 0x25, 0x32, 0x4d, 0x21, 0x2e, 0x4a, 0x7d, 0x84, 0x94, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 46 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xd1, 0xd4, 0xd9, 0x2d, 0x39, 0x54, 0x24, 0x31, 0x4c, 0x25, 0x32, 0x4c, 0x25, 0x32, 0x4d, 0x23, 0x2f, 0x4b, 0x4e, 0x58, 0x6e, 0xf5, 0xf6, 0xf7, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 47 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xec, 0xee, 0xf0, 0x44, 0x4f, 0x66, 0x23, 0x30, 0x4b, 0x25, 0x32, 0x4c, 0x25, 0x32, 0x4c, 0x24, 0x31, 0x4c, 0x31, 0x3d, 0x56, 0xdb, 0xdd, 0xe1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 48 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xba, 0xbf, 0xc7, 0x53, 0x5d, 0x72, 0x35, 0x42, 0x5a, 0x48, 0x53, 0x69, 0xa4, 0xa9, 0xb4, 0xfc, 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 49 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xd9, 0xdb, 0xdf, 0x62, 0x6b, 0x7e, 0x39, 0x45, 0x5d, 0x40, 0x4b, 0x62, 0x85, 0x8d, 0x9b, 0xf0, 0xf1, 0xf2, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 50 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xed, 0xee, 0xf0, 0x7d, 0x84, 0x94, 0x3d, 0x49, 0x61, 0x3a, 0x46, 0x5e, 0x6d, 0x76, 0x87, 0xe0, 0xe1, 0xe5, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 51 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 52 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 53 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 54 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 55 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 56 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 57 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 58 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 59 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 60 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 61 | 0xff, 0xfd, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 62 | 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 63 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xf9, 0xfb, 64 | 0xfd, 0xe1, 0xeb, 0xf6, 0xd5, 0xe3, 0xf2, 0xd6, 0xe3, 0xf2, 0xe9, 0xf1, 0xf8, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfe, 0xe8, 0xf0, 0xf8, 0xd6, 0xe4, 0xf2, 0xd4, 0xe3, 0xf1, 0xdc, 65 | 0xe8, 0xf4, 0xf4, 0xf7, 0xfb, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 66 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa5, 0xc4, 0xe3, 0x4d, 0x8a, 0xc8, 0x4f, 0x8a, 0xc9, 0x4f, 0x8b, 0xc9, 0x84, 0xad, 0xd9, 0xfe, 0xfe, 0xfe, 0xc8, 0xdb, 0xee, 0x5e, 0x94, 0xcd, 0x2e, 0x75, 67 | 0xbf, 0x23, 0x6e, 0xbb, 0x20, 0x6c, 0xbb, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x3b, 0x7e, 0xc3, 0x8e, 0xb4, 0xdc, 0xef, 0xf3, 0xf7, 0xe6, 0xe7, 0xe9, 0xed, 0xee, 0xef, 0xfe, 0xfe, 0xfe, 0xe4, 0xee, 0xf7, 0x7f, 0xaa, 0xd7, 0x38, 0x7c, 0xc1, 0x25, 0x6f, 0xbb, 0x21, 0x6c, 0xbb, 0x20, 0x6c, 0xbb, 0x22, 68 | 0x6d, 0xbb, 0x29, 0x72, 0xbd, 0x4c, 0x89, 0xc8, 0xa7, 0xc5, 0xe4, 0xf8, 0xfb, 0xfc, 0xea, 0xeb, 0xed, 0xe7, 0xe8, 0xea, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 69 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfc, 0xfc, 0xfc, 0x6f, 0x96, 0xc1, 0x26, 0x70, 0xbc, 0x27, 0x70, 0xbc, 0x27, 0x71, 0xbd, 0x51, 0x86, 0xbf, 0x7b, 0xa7, 0xd5, 0x22, 0x6d, 0xbb, 0x26, 0x6f, 0xbc, 0x25, 0x6f, 70 | 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x23, 0x6d, 0xbb, 0x2c, 0x70, 0xb7, 0x28, 0x40, 0x63, 0x2b, 0x37, 0x50, 0x58, 0x79, 0xa1, 0x2b, 0x73, 0xbe, 0x24, 0x6e, 0xbb, 0x26, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 71 | 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x26, 0x70, 0xbc, 0x21, 0x6c, 0xba, 0x35, 0x75, 0xb8, 0x2a, 0x3e, 0x5d, 0x29, 0x36, 0x50, 0x4e, 0x58, 0x6e, 0xc8, 0xcb, 0xd2, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 72 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x8d, 0x93, 0xa1, 0x21, 0x4e, 0x83, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x24, 0x6c, 0xb9, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x23, 0x6e, 0xbb, 0x20, 0x6b, 73 | 0xba, 0x25, 0x6f, 0xbc, 0x23, 0x6e, 0xbb, 0x20, 0x6b, 0xba, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x25, 0x6c, 0xb6, 0x24, 0x4f, 0x82, 0x26, 0x71, 0xbe, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x24, 0x6e, 0xbb, 0x20, 0x6b, 0xba, 0x25, 0x6f, 0xbc, 0x23, 0x6e, 0xbb, 0x20, 74 | 0x6b, 0xba, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6a, 0xb3, 0x24, 0x37, 0x56, 0x25, 0x32, 0x4d, 0x27, 0x34, 0x4e, 0xc8, 0xcc, 0xd2, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 75 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xde, 0xe0, 0xe3, 0x25, 0x32, 0x4c, 0x25, 0x51, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x2a, 0x73, 0xbe, 0x8b, 0xb3, 0xdb, 0xcd, 0xde, 76 | 0xef, 0xe7, 0xf0, 0xf7, 0xe0, 0xeb, 0xf5, 0xb7, 0xd0, 0xe9, 0x4e, 0x8a, 0xc9, 0x24, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbb, 0x25, 0x6f, 0xbb, 0x27, 0x71, 0xbd, 0x7c, 0xa8, 0xd6, 0xca, 0xdc, 0xef, 0xe7, 0xef, 0xf7, 0xe1, 0xeb, 0xf5, 0xb7, 77 | 0xcf, 0xe9, 0x53, 0x8e, 0xca, 0x24, 0x6e, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x24, 0x5f, 0xa0, 0x24, 0x30, 0x4a, 0x25, 0x32, 0x4d, 0x4d, 0x57, 0x6d, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 78 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xa5, 0xaa, 0xb5, 0x21, 0x2e, 0x49, 0x24, 0x50, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x24, 0x6b, 0xb5, 0x78, 0x8a, 0xa4, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 79 | 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfc, 0xfd, 0xfd, 0xd1, 0xd4, 0xd9, 0x21, 0x58, 0x96, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x26, 0x6e, 0xba, 0x46, 0x60, 0x83, 0xfd, 0xfe, 0xfe, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfe, 0xfe, 0xfd, 80 | 0xfe, 0xfe, 0xf6, 0xf7, 0xf8, 0x30, 0x66, 0xa2, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x23, 0x39, 0x5a, 0x24, 0x31, 0x4d, 0x29, 0x36, 0x50, 0xeb, 0xec, 0xee, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 81 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x9e, 0xa3, 0xaf, 0x21, 0x2e, 0x49, 0x24, 0x50, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbd, 0x23, 0x44, 0x6e, 0x74, 0x7c, 0x8e, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 82 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfe, 0xfe, 0xcd, 0xd0, 0xd6, 0x20, 0x31, 0x4f, 0x24, 0x6c, 0xb7, 0x25, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbd, 0x25, 0x4d, 0x7e, 0x43, 0x4e, 0x65, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 83 | 0xfe, 0xfe, 0xf7, 0xf8, 0xf9, 0x31, 0x40, 0x5c, 0x25, 0x6c, 0xb7, 0x25, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbd, 0x24, 0x4e, 0x80, 0x24, 0x31, 0x4b, 0x28, 0x35, 0x4f, 0xe8, 0xe9, 0xeb, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 84 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xd0, 0xd3, 0xd9, 0x22, 0x2f, 0x4a, 0x24, 0x50, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x24, 0x69, 0xb1, 0x21, 0x2e, 0x4a, 0xa8, 0xad, 0xb8, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 85 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf3, 0xf3, 0xf5, 0x33, 0x3e, 0x56, 0x25, 0x5d, 0x9c, 0x25, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x24, 0x6c, 0xb8, 0x23, 0x33, 0x50, 0x71, 0x7a, 0x8b, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 86 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x57, 0x5f, 0x73, 0x25, 0x5c, 0x99, 0x25, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x24, 0x59, 0x94, 0x25, 0x31, 0x4b, 0x40, 0x4c, 0x63, 0xfb, 0xfb, 0xfb, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 87 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x66, 0x6f, 0x81, 0x23, 0x4f, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x24, 0x5f, 0xa0, 0x44, 0x4e, 0x64, 0xf5, 0xf5, 0xf6, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 88 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x98, 0x9e, 0xaa, 0x22, 0x4d, 0x80, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x25, 0x61, 0xa2, 0x2b, 0x35, 0x4e, 0xdb, 0xdd, 0xe1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 89 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xc7, 0xca, 0xd1, 0x26, 0x4f, 0x81, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x25, 0x5c, 0x99, 0x22, 0x2d, 0x48, 0xa8, 0xad, 0xb8, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 90 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf4, 0xf4, 0xf6, 0x58, 0x81, 0xaf, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x40, 0x76, 0xb0, 0xe6, 0xe6, 0xe9, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 91 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x7d, 0x9e, 0xc2, 0x23, 0x6e, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x35, 0x6a, 0xa5, 0xc6, 0xc8, 0xce, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 92 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x96, 0xb5, 0xd4, 0x22, 0x6d, 0xbc, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x2d, 0x64, 0xa1, 0xa1, 0xa5, 0xb0, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 93 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0x91, 0xb6, 0xdd, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 94 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa5, 0xc4, 0xe3, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x6c, 0x9f, 0xd2, 0xfd, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 95 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa9, 0xc7, 0xe4, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 96 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0x90, 0xb6, 0xdd, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 97 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa6, 0xc4, 0xe3, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x6c, 0x9f, 0xd2, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 98 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa9, 0xc7, 0xe5, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd1, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 99 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0x90, 0xb6, 0xdd, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 100 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa6, 0xc4, 0xe3, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x6c, 0x9f, 0xd2, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 101 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa9, 0xc7, 0xe5, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x68, 0x9b, 0xd1, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 102 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0x90, 0xb6, 0xdd, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 103 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa6, 0xc4, 0xe3, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x6c, 0x9f, 0xd2, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 104 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa9, 0xc7, 0xe5, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x68, 0x9b, 0xd1, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 105 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0x90, 0xb6, 0xdd, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 106 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa6, 0xc4, 0xe3, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x6c, 0x9f, 0xd2, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 107 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa9, 0xc7, 0xe5, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x68, 0x9b, 0xd1, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 108 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0x90, 0xb5, 0xdc, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9a, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 109 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa5, 0xc4, 0xe3, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x6c, 0x9f, 0xd1, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 110 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xa9, 0xc7, 0xe5, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x67, 0x9b, 0xd0, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 111 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x8b, 0xb0, 0xd8, 0x24, 0x6e, 0xbb, 0x25, 0x6f, 0xbc, 0x26, 0x6f, 0xbc, 0x63, 0x97, 0xcd, 0xfd, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 112 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xa5, 0xc3, 0xe2, 0x22, 0x6d, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x5e, 0x91, 0xc6, 0xfc, 0xfb, 0xfb, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 113 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xaa, 0xc7, 0xe4, 0x21, 0x6c, 0xbb, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x53, 0x88, 0xc0, 0xf4, 0xf4, 0xf4, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 114 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xc7, 0xca, 0xd0, 0x2b, 0x57, 0x8a, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6e, 0xbb, 0x27, 0x5e, 0x9c, 0xa4, 0xa7, 0xb1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 115 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xe7, 0xe9, 0xeb, 0x42, 0x67, 0x92, 0x25, 0x70, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x23, 0x59, 0x95, 0x71, 0x78, 0x88, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 116 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf8, 0xf8, 0xf9, 0x5f, 0x80, 0xa8, 0x24, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x23, 0x5a, 0x98, 0x4a, 0x54, 0x69, 0xee, 0xef, 0xf1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 117 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf2, 0xf3, 0xf4, 0x38, 0x43, 0x5b, 0x25, 0x51, 0x85, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x25, 0x5c, 0x9a, 0x27, 0x32, 0x4c, 0xd9, 0xdb, 0xe0, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 118 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x5f, 0x69, 0x7c, 0x24, 0x4a, 0x7a, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x24, 0x5a, 0x96, 0x21, 0x2d, 0x47, 0xaf, 0xb4, 0xbe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 119 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x95, 0x9b, 0xa8, 0x22, 0x46, 0x75, 0x25, 0x70, 0xbe, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x24, 0x5b, 0x99, 0x24, 0x2f, 0x49, 0x71, 0x79, 0x8b, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 120 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xb6, 0xba, 0xc3, 0x20, 0x2d, 0x48, 0x24, 0x50, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x24, 0x5c, 0x99, 0x22, 0x2e, 0x48, 0x8a, 0x91, 0x9f, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 121 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfe, 0xfe, 0xdf, 0xe0, 0xe4, 0x25, 0x32, 0x4d, 0x24, 0x4a, 0x79, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x24, 0x5a, 0x96, 0x25, 0x31, 0x4a, 0x51, 0x5b, 0x71, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 122 | 0xfe, 0xfe, 0xfc, 0xfd, 0xfd, 0x3d, 0x49, 0x61, 0x25, 0x4a, 0x77, 0x25, 0x70, 0xbe, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x24, 0x5b, 0x99, 0x24, 0x30, 0x49, 0x2f, 0x3b, 0x54, 0xf2, 0xf3, 0xf4, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 123 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x97, 0x9e, 0xaa, 0x22, 0x2e, 0x49, 0x24, 0x50, 0x84, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x24, 0x5c, 0x99, 0x24, 0x30, 0x49, 0x6e, 0x77, 0x89, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 124 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xcb, 0xce, 0xd4, 0x20, 0x2e, 0x49, 0x24, 0x4a, 0x79, 0x25, 0x6f, 0xbd, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbc, 0x24, 0x5a, 0x96, 0x25, 0x31, 0x4a, 0x40, 0x4b, 0x63, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 125 | 0xfe, 0xfe, 0xf5, 0xf6, 0xf7, 0x30, 0x3d, 0x56, 0x24, 0x49, 0x77, 0x25, 0x70, 0xbe, 0x25, 0x6f, 0xbc, 0x25, 0x6f, 0xbb, 0x24, 0x5b, 0x99, 0x24, 0x30, 0x49, 0x27, 0x34, 0x4f, 0xe4, 0xe5, 0xe8, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 126 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xbb, 0xbf, 0xc7, 0x20, 0x2d, 0x48, 0x24, 0x51, 0x86, 0x25, 0x71, 0xc0, 0x25, 0x71, 0xbf, 0x25, 0x70, 0xbf, 0x24, 0x5d, 0x9c, 0x22, 0x2e, 0x48, 0x8e, 0x95, 0xa3, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 127 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xe3, 0xe5, 0xe8, 0x28, 0x34, 0x4f, 0x24, 0x4b, 0x7b, 0x25, 0x72, 0xc1, 0x25, 0x71, 0xbf, 0x25, 0x71, 0xbf, 0x24, 0x5b, 0x98, 0x25, 0x30, 0x4a, 0x57, 0x61, 0x76, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 128 | 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0x41, 0x4d, 0x64, 0x25, 0x4a, 0x79, 0x25, 0x71, 0xc1, 0x25, 0x71, 0xbf, 0x25, 0x70, 0xbf, 0x24, 0x5d, 0x9b, 0x24, 0x30, 0x4a, 0x32, 0x3e, 0x57, 0xf5, 0xf6, 0xf7, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 129 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf4, 0xf5, 0xf6, 0x3c, 0x48, 0x60, 0x25, 0x38, 0x58, 0x24, 0x3e, 0x63, 0x24, 0x3e, 0x63, 0x24, 0x3e, 0x63, 0x25, 0x3b, 0x5d, 0x28, 0x35, 0x4f, 0xdf, 0xe1, 0xe5, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 130 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x66, 0x6f, 0x82, 0x24, 0x36, 0x55, 0x24, 0x3e, 0x63, 0x24, 0x3e, 0x63, 0x24, 0x3e, 0x63, 0x24, 0x3a, 0x5b, 0x21, 0x2e, 0x49, 0xb5, 0xb9, 0xc2, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 131 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0x9a, 0xa0, 0xac, 0x22, 0x34, 0x53, 0x24, 0x3e, 0x63, 0x24, 0x3e, 0x63, 0x24, 0x3e, 0x63, 0x24, 0x3a, 0x5c, 0x24, 0x30, 0x4b, 0x75, 0x7d, 0x8e, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 132 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xd0, 0xd2, 0xd8, 0x32, 0x3e, 0x58, 0x21, 0x2f, 0x4b, 0x24, 0x32, 0x4d, 0x22, 0x30, 0x4b, 0x27, 0x34, 0x50, 0xad, 0xb2, 0xbc, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 133 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xea, 0xeb, 0xee, 0x4d, 0x58, 0x6e, 0x20, 0x2e, 0x4a, 0x24, 0x32, 0x4d, 0x23, 0x30, 0x4c, 0x22, 0x30, 0x4b, 0x7c, 0x84, 0x94, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 134 | 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfa, 0xfa, 0xfb, 0x70, 0x79, 0x8a, 0x21, 0x2f, 0x4b, 0x23, 0x31, 0x4d, 0x24, 0x31, 0x4d, 0x21, 0x2e, 0x4a, 0x53, 0x5e, 0x73, 0xf0, 0xf1, 0xf3, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 135 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xe9, 0xeb, 0xed, 0x9c, 0xa1, 0xae, 0x6a, 0x73, 0x86, 0x8f, 0x96, 0xa3, 0xda, 0xdc, 0xe1, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 136 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xf6, 0xf6, 0xf7, 0xab, 0xb0, 0xba, 0x70, 0x78, 0x8a, 0x81, 0x88, 0x98, 0xc7, 0xca, 0xd1, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 137 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfe, 0xc1, 0xc4, 0xcb, 0x7a, 0x82, 0x92, 0x73, 0x7b, 0x8c, 0xb4, 0xb8, 0xc1, 0xf9, 0xfa, 0xfb, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 138 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 139 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 140 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 141 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 142 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 143 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 144 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 145 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 146 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 147 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 148 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 149 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 150 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 151 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 152 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 153 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 154 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 155 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 156 | }; 157 | -------------------------------------------------------------------------------- /workspace/pub_image/main/pub_image.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "sensor_msgs/msg/image.hpp" 20 | #include "mros_image.h" 21 | 22 | 23 | extern "C" void app_main(void) 24 | { 25 | /* connect to the network */ 26 | if (mros2_platform_network_connect()) 27 | { 28 | MROS2_INFO("successfully connect and setup network\r\n---"); 29 | } 30 | else 31 | { 32 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 33 | return; 34 | } 35 | 36 | MROS2_INFO("%s start!", MROS2_PLATFORM_NAME); 37 | MROS2_INFO("app name: pub_image"); 38 | 39 | mros2::init(0, NULL); 40 | MROS2_DEBUG("mROS 2 initialization is completed"); 41 | 42 | mros2::Node node = mros2::Node::create_node("mros2_node"); 43 | mros2::Publisher pub = node.create_publisher("to_linux", 10); 44 | 45 | osDelay(100); 46 | MROS2_INFO("ready to pub image\r\n---"); 47 | 48 | auto msg = sensor_msgs::msg::Image(); 49 | 50 | while (1) { 51 | msg.sec = time(NULL); 52 | msg.nanosec = 0; 53 | msg.frame_id = "frame"; 54 | msg.height = MROS_IMAGE_HEIGHT; 55 | msg.width = MROS_IMAGE_WIDTH; 56 | msg.encoding = "rgb8"; 57 | msg.is_bigendian = 0; 58 | msg.step = MROS_IMAGE_WIDTH * 3; 59 | size_t image_size = sizeof(mros_image); 60 | msg.data.resize(image_size); 61 | std::memcpy(reinterpret_cast(&msg.data[0]), 62 | mros_image, image_size); 63 | 64 | MROS2_INFO("publishing image"); 65 | pub.publish(msg); 66 | 67 | osDelay(1000); 68 | } 69 | 70 | mros2::spin(); 71 | return; 72 | } 73 | -------------------------------------------------------------------------------- /workspace/pub_long_string_sub_crc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(pub_long_string_sub_crc) -------------------------------------------------------------------------------- /workspace/pub_long_string_sub_crc/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "pub_long_string_sub_crc.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/pub_long_string_sub_crc/main/long_text.txt: -------------------------------------------------------------------------------- 1 | "[![build](https://github.com/mROS-base/mros2-mbed/actions/workflows/build.yaml/badge.svg)](https://github.com/mROS-base/mros2-mbed/actions/workflows/build.yaml)\n" 2 | "\n" 3 | "# mros2-mbed\n" 4 | "\n" 5 | "mROS 2 (formally `mros2`) realizes a agent-less and lightweight runtime environment compatible with ROS 2 for embedded devices.\n" 6 | "mROS 2 mainly offers pub/sub APIs compatible with [rclcpp](https://docs.ros.org/en/rolling/p/rclcpp/index.html) for embedded devices.\n" 7 | "\n" 8 | "mROS 2 consists of communication library for pub/sub APIs, RTPS protocol, UDP/IP stack, and real-time kernel.\n" 9 | "This repository provides the reference implementation of mROS 2 that can be operated on the Mbed enabled board.\n" 10 | "Please also check [mros2 repository](https://github.com/mROS-base/mros2) for more details and another implementations.\n" 11 | "\n" 12 | "## Supported environment\n" 13 | "\n" 14 | "- Mbed device\n" 15 | " - Board: Mbed enabled boards having an Ethernet port \n" 16 | " - For now, these boards below are confirmed to run the example on them.\n" 17 | " - [STM32 NUCLEO-F767ZI](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html)\n" 18 | " - [STM32 NUCLEO-H743ZI2](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html)\n" 19 | " - These boards below are also confirmed but not always supported in the latest version (due to our development resources,,,).\n" 20 | " - [STM32 NUCLEO-F429ZI](https://www.st.com/en/evaluation-tools/nucleo-f429zi.html)\n" 21 | " - [STM32 F746NG-Discovery](https://www.st.com/ja/evaluation-tools/32f746gdiscovery.html)\n" 22 | " - [STM32 F769NI-Discovery](https://www.st.com/ja/evaluation-tools/32f769idiscovery.html)\n" 23 | " - [Seeed Arch Max V1.1](https://wiki.seeedstudio.com/Arch_Max_v1.1/)\n" 24 | " - [RENESAS GR-MANGO](https://www.renesas.com/products/gadget-renesas/boards/gr-mango)\n" 25 | " - Kernel: [Mbed OS 6](https://github.com/ARMmbed/mbed-os)\n" 26 | " - check the Mbed website for [the boards list](https://os.mbed.com/platforms/?q=&Mbed+OS+6=Bare+metal&Mbed+OS+6=RTOS&Communication=Ethernet) where mros2 may work. Please let us know if you find a new board that can work as mros2 enabled device.\n" 27 | "- Host environment\n" 28 | " - [ROS 2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) on Ubuntu 22.04 LTS\n" 29 | " - [ROS 2 Foxy Fitzroy](https://docs.ros.org/en/foxy/index.html) on Ubuntu 20.04 LTS\n" 30 | "- Network setting\n" 31 | " - Make sure both the device and the host are connected to the wired network with the following setting, since they are statically configured to the board (if you want to change them, please edit both `app.cpp` and `include/rtps/config.h`).\n" 32 | " - IP address: 192.168.11.x\n" 33 | " - .2 will be assigned to the board\n" 34 | " - Netmask: 255.255.255.0\n" 35 | " - Gateway: 192.168.11.1\n" 36 | " - The firewall on the host (Ubuntu) needs to be disabled for ROS 2 (DDS) communication (e.g. `$ sudo ufw disable`).\n" 37 | " - If the host is connected to the Internet other than wired network (e.g., Wi-Fi), communication with mros2 may not work properly. In that case, please turn off them.\n" 38 | "\n" 39 | "## Getting Started\n" 40 | "\n" 41 | "1. Prepare these items below.\n" 42 | "- Host PC having an Ethernet port whose network is set to the above and a docker environment.\n" 43 | "- Mbed board having an Ethernet port (listed above).\n" 44 | "2. Build Mbed executable binary using [the Docker environment for Mbed CLI2](https://github.com/ARMmbed/mbed-os/pkgs/container/mbed-os-env). \n" 45 | "(You can also use the native environment where MBed CLI2 could work well. Please add `native` to 4th arg. (see [the example instruction to prepare native env](https://github.com/mROS-base/mros2-mbed/commit/90225c77e07e5cedc8473285b457827cb047e481)))\n" 46 | "```\n" 47 | "git clone https://github.com/mROS-base/mros2-mbed\n" 48 | "cd mros2-mbed\n" 49 | "#(Please replace the [TARGET] with the ones as below.)\n" 50 | "# +-------------------+----------------+\n" 51 | "# | Your target board | [TARGET] |\n" 52 | "# +-------------------+----------------+\n" 53 | "# | NUCLEO-F767ZI | NUCLEO_F767ZI |\n" 54 | "# | NUCLEO-H743ZI2 | NUCLEO_H743ZI2 |\n" 55 | "# | NUCLEO-F429ZI | NUCLEO_F429ZI |\n" 56 | "# | F746NG-Discovery | DISCO_F746NG |\n" 57 | "# | F769NI-Discovery | DISCO_F769NI |\n" 58 | "# | Arch Max v1.1 | ARCH_MAX |\n" 59 | "# | GR-MANGO | GR_MANGO |\n" 60 | "# +-------------------+----------------+\n" 61 | "./build.bash all [TARGET] echoback_string\n" 62 | "```\n" 63 | "After that, you will find an executable binary is created in the path below.\n" 64 | "```\n" 65 | "cmake_build/[TARGET]/develop/GCC_ARM/mros2-mbed.bin\n" 66 | "```\n" 67 | "3. Connect the PC and Mbed Board with USB and LAN cables.\n" 68 | "4. Open Serial Console of the Mbed board. (115200bps)\n" 69 | "5. Copy the executable binary above to the Mbed Board.\n" 70 | " (you may find it in the Nautilus file manager as NODE_F429ZI, F767ZI or DAPLINK.)\n" 71 | "```\n" 72 | "mbed mros2 start! \n" 73 | "app name: echoback_string \n" 74 | "[MROS2LIB] mros2_init task start \n" 75 | "mROS 2 initialization is completed \n" 76 | " \n" 77 | "[MROS2LIB] create_node \n" 78 | "[MROS2LIB] start creating participant \n" 79 | "[MROS2LIB] successfully created participant \n" 80 | "[MROS2LIB] create_publisher complete. \n" 81 | "[MROS2LIB] create_subscription complete. \n" 82 | "[MROS2LIB] Initilizing Domain complete \n" 83 | "ready to pub/sub message \n" 84 | " \n" 85 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 0' \n" 86 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 1' \n" 87 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 2' \n" 88 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 3' \n" 89 | "...(SNIPPED)...\n" 90 | "```\n" 91 | "6. One of the easiest way to operate the host is using Docker. On the host terminal, type the command below.\n" 92 | "```\n" 93 | "docker run --rm -it --net=host ros:humble /bin/bash \\n" 94 | " -c \"source /opt/ros/humble/setup.bash &&\n" 95 | " cd &&\n" 96 | " git clone https://github.com/mROS-base/mros2-host-examples &&\n" 97 | " cd mros2-host-examples &&\n" 98 | " colcon build --packages-select mros2_echoreply_string &&\n" 99 | " source install/setup.bash &&\n" 100 | " ros2 run mros2_echoreply_string echoreply_node\"\n" 101 | "```\n" 102 | "Then, we can confirm the communication between the host and Mbed board via ROS 2 topic.\n" 103 | "```\n" 104 | "Cloning into 'mros2-host-examples'...\n" 105 | "remote: Enumerating objects: 831, done.\n" 106 | "remote: Counting objects: 100% (85/85), done.\n" 107 | "remote: Compressing objects: 100% (68/68), done.\n" 108 | "remote: Total 831 (delta 46), reused 26 (delta 15), pack-reused 746\n" 109 | "Receiving objects: 100% (831/831), 96.01 KiB | 7.38 MiB/s, done.\n" 110 | "Resolving deltas: 100% (448/448), done.\n" 111 | "Starting >>> mros2_echoreply_string\n" 112 | "Finished <<< mros2_echoreply_string [9.02s] \n" 113 | "\n" 114 | "Summary: 1 package finished [9.17s]\n" 115 | "[INFO] [1666012200.122092282] [mros2_echoreply_node]: \n" 116 | "Subscribed msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 7'\n" 117 | "[INFO] [1666012200.122210443] [mros2_echoreply_node]: \n" 118 | "Publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 7'\n" 119 | "[INFO] [1666012201.127168943] [mros2_echoreply_node]: \n" 120 | "Subscribed msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 8'\n" 121 | "[INFO] [1666012201.127216518] [mros2_echoreply_node]: \n" 122 | "Publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 8'\n" 123 | "[INFO] [1666012202.132162620] [mros2_echoreply_node]: \n" 124 | "Subscribed msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 9'\n" 125 | "[INFO] [1666012202.132208473] [mros2_echoreply_node]: \n" 126 | "Publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 9'\n" 127 | "[INFO] [1666012203.137265544] [mros2_echoreply_node]: \n" 128 | "...(SNIPPED)...\n" 129 | "```\n" 130 | "serial console on the board\n" 131 | "```\n" 132 | "...(SNIPPED)...\n" 133 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 5' \n" 134 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 6' \n" 135 | "[MROS2LIB] subscriber matched with remote publisher \n" 136 | "[MROS2LIB] publisher matched with remote subscriber \n" 137 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 7' \n" 138 | "subscribed msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 7' \n" 139 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 8' \n" 140 | "subscribed msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 8' \n" 141 | "publishing msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 9' \n" 142 | "subscribed msg: 'Hello from mros2-mbed onto NUCLEO_F767ZI: 9' \n" 143 | "...(SNIPPED)...\n" 144 | "```\n" 145 | "\n" 146 | "## Examples\n" 147 | "\n" 148 | "This repository contains some example applications in [workspace/](workspace/) to communicate with ROS 2 nodes on the host.\n" 149 | "You can switch the example by specifying the third argument of `build.bash`.\n" 150 | "Of course you can also create a new program file and specify it as your own application.\n" 151 | "\n" 152 | "Please also check [mROS-base/mros2-host-examples](https://github.com/mROS-base/mros2-host-examples) repository for more detail about the host examples.\n" 153 | "\n" 154 | "### echoback_string (default)\n" 155 | "\n" 156 | "- Description:\n" 157 | " - The mROS 2 node on the embedded board publishes `string` (`std_msgs::msg::String`) message to `/to_linux` topic.\n" 158 | " - (The node on the host will echoreply this message as it is.)\n" 159 | " - The mROS 2 node subscribes the replied message from `/to_stm` topic.\n" 160 | "- Host operation:\n" 161 | " - `$ ros2 run mros2_echoreply_string echoreply_node`\n" 162 | "\n" 163 | "### echoreply_string\n" 164 | "\n" 165 | "- Description:\n" 166 | " - The mROS 2 node on the embedded board subscribes `string` (`std_msgs::msg::String`) message from `/to_stm` topic.\n" 167 | " - And then publishes this `string` message as it is to `/to_linux` as the reply.\n" 168 | "- Host operation:\n" 169 | " - at first terminal: `$ ros2 run mros2_echoback_string sub_node`\n" 170 | " - and then, at second terminal: `$ ros2 run mros2_echoback_string pub_node`\n" 171 | " - or, at one terminal:\n" 172 | " - `$ ros2 launch mros2_echoback_string pubsub.launch.py`\n" 173 | "\n" 174 | "### pub_float32\n" 175 | "\n" 176 | "- Description:\n" 177 | " - The mROS 2 node on the embedded board publishes `float32` (`std_msgs::msg::Float32`) message to `/to_linux` topic.\n" 178 | " - Note that this application just print whether the value of message is less than 0.0, between 0.0 and 1.0, or greater than 1.0.\n" 179 | " - If you want to print float value in serial console, you need to add `\"target.printf_lib\": \"std\"` into mbed_app.json (see [detail](https://forums.mbed.com/t/float-printf-doesnt-work-in-desktop-version/9164)). Note that linking std lib will increase the size of Flash memory.\n" 180 | "- Host operation:\n" 181 | " - `$ ros2 run mros2_sub_float32 sub_node`\n" 182 | " - or, `$ ros2 launch mros2_sub_float32 sub.launch.py`\n" 183 | "\n" 184 | "### sub_uint16\n" 185 | "\n" 186 | "- Description:\n" 187 | " - The mROS 2 node on the embedded board subscribes `uint16` (`std_msgs::msg::UInt16`) message from `/to_stm` topic.\n" 188 | "- Host operation:\n" 189 | " - `$ ros2 run mros2_pub_uint16 pub_node`\n" 190 | " - or, `$ ros2 launch mros2_pub_uint16 pub.launch.py`\n" 191 | "\n" 192 | "### pub_twist\n" 193 | "\n" 194 | "- Description:\n" 195 | " - The mROS 2 node on the embedded board publishes `Twist` (`geometry_msgs::msg::Twist`) message to `/cmd_vel` topic.\n" 196 | " - This application requires to generated header files for `Twist` and `Vector3`. See detail in [/README.md#generating-header-files-for-custom-msgtypes](./README.md#generating-header-files-for-custom-msgtypes).\n" 197 | "- Host operation:\n" 198 | " - `$ ros2 run mros2_sub_twist sub_node`\n" 199 | " - or, `$ ros2 launch mros2_sub_twist sub.launch.py`\n" 200 | "\n" 201 | "### sub_pose\n" 202 | "\n" 203 | "- Description:\n" 204 | " - The mROS 2 node on the embedded board subscibes `Pose` (`geometry_msgs::msg::Pose`) message to `/cmd_vel` topic.\n" 205 | " - This application requires to generated header files for `Pose`, `Point` and `Quartenion`. See detail in [/README.md#generating-header-files-for-custom-msgtypes](./README.md#generating-header-files-for-custom-msgtypes).\n" 206 | "- Host operation:\n" 207 | " - `$ ros2 run mros2_pub_pose pub_node`\n" 208 | " - or, `$ ros2 launch mros2_pub_pose pub.launch.py`\n" 209 | "\n" 210 | "### mturtle_teleop\n" 211 | "\n" 212 | "- Description:\n" 213 | " - This is a sample application along with [mturtlesim](https://github.com/mROS-base/ros_tutorials/tree/mros2/humble-devel/turtlesim) (mros2 dedicated version of turtlesim).\n" 214 | " - The mROS 2 node on the embedded board publishes `Twist` (`geometry_msgs::msg::Twist`) message to `/turtle1/cmd_vel` topic, according to the input from keyboard via serial console.\n" 215 | "- Please see [mturtle_teleop/README.md](workspace/mturtle_teleop/README.md) for more detail including host operation.\n" 216 | "\n" 217 | "### mturtle_teleop_joy\n" 218 | "\n" 219 | "- Description:\n" 220 | " - This is a sample application along with [mturtlesim](https://github.com/mROS-base/ros_tutorials/tree/mros2/humble-devel/turtlesim) (mros2 dedicated version of turtlesim).\n" 221 | " - The mROS 2 node on the embedded board publishes `Twist` (`geometry_msgs::msg::Twist`) message to `/turtle1/cmd_vel` topic, according to the input from Joystick module.\n" 222 | "- Please see [mturtle_teleop_joy/README.md](workspace/mturtle_teleop_joy/README.md) for more detail including host operation.\n" 223 | "\n" 224 | "## Files for the application\n" 225 | "\n" 226 | "On this platform, the mros2 application consists of the following files:\n" 227 | "\n" 228 | "- app.cpp: \n" 229 | " - main source of the application\n" 230 | " - note that the file name must be this in order to generate the templates of pub/sub functions in the build step.\n" 231 | "- templates.hpp:\n" 232 | " - the templates of pub/sub functions\n" 233 | " - this file will be automatically generated/modified during the build step, so you do not have to care about this file.\n" 234 | "\n" 235 | "## Generating header files for custom MsgTypes\n" 236 | "\n" 237 | "You can use almost any [built-in-types in ROS 2](https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html#field-types) on the embedded device.\n" 238 | "\n" 239 | "In additon, you can define a customized message type (e.g., `Twist.msg`) in the same way as in ROS 2, and use its header file for your application. This section describes how to generate header files for your own MsgTypes (`geometry_msgs::msg::Twist` as an example).\n" 240 | "\n" 241 | "### Prepare .msg files\n" 242 | "\n" 243 | "`.msg` files are simple text files that describe the fields of a ROS message (see [About ROS 2 interface](https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html)). In mros2, they are used to generate header files for messages in embedded applications.\n" 244 | "\n" 245 | "Prepare `Twist.msg` file and make sure it is in `workspace/custom_msgs/geometry_msgs/msg/`.\n" 246 | "\n" 247 | "```\n" 248 | "$ cat workspace/custom_msgs/geometry_msgs/msg/Twist.msg\n" 249 | "geometry_msgs/msg/Vector3 linear\n" 250 | "geometry_msgs/msg/Vector3 angular\n" 251 | "```\n" 252 | "\n" 253 | "In this example, `Twist` has a nested structure with `Vector3` as a child element. So you also need to prepare its file.\n" 254 | "\n" 255 | "```\n" 256 | "$ cat workspace/custom_msgs/geometry_msgs/msg/Vector3.msg\n" 257 | "float64 x\n" 258 | "float64 y\n" 259 | "float64 z\n" 260 | "```\n" 261 | "\n" 262 | "### Generate header files\n" 263 | "\n" 264 | "To generate header files for `Twist` and `Vector3`, run the following command in `workspace/`.\n" 265 | "\n" 266 | "```\n" 267 | "$ cd workspace\n" 268 | "$ python3 ../mros2/mros2_header_generator/header_generator.py geometry_msgs/msg/Twist.msg\n" 269 | "```\n" 270 | "\n" 271 | "Make sure header files for custom MsgType are generated in `custom_msgs/`.\n" 272 | "\n" 273 | "```\n" 274 | "$ ls -R custom_msgs/\n" 275 | "custom_msgs/:\n" 276 | "geometry_msgs\n" 277 | "\n" 278 | "custom_msgs/geometry_msgs:\n" 279 | "msg\n" 280 | "\n" 281 | "custom_msgs/geometry_msgs/msg:\n" 282 | "twist.hpp vector3.hpp Twist.msg Vector3.msg\n" 283 | "```\n" 284 | "\n" 285 | "You can now use them in your applicaton like this.\n" 286 | "\n" 287 | "```\n" 288 | "#include \"mros2.hpp\"\n" 289 | "#include \"geometry_msgs/msg/vector3.hpp\"\n" 290 | "#include \"geometry_msgs/msg/twist.hpp\"\n" 291 | "\n" 292 | "int main(int argc, char * argv[])\n" 293 | "{\n" 294 | "\n" 295 | " pub = node.create_publisher(\"cmd_vel\", 10);\n" 296 | "\n" 297 | "```\n" 298 | "\n" 299 | "## Tips 1: Configure the network\n" 300 | "\n" 301 | "`include/rtps/config.h` is the configuration file for embeddedRTPS.\n" 302 | "We may be able to realize the RTPS communication to the appropriate configuration by editting this file.\n" 303 | "\n" 304 | "And also, you can configure for lwIP (UDP/IP) by `mbed_app.json`. \n" 305 | "Currently, we are unable to communicate large size of messages probably due to these configurations. \n" 306 | "\n" 307 | "We should seek the appropreate configurations or how to fit them to the demand of applications.\n" 308 | "Please let us know about them if you have any opinions or awesome knowledges! \n" 309 | "\n" 310 | "## Tips 2: Getting started in 5 minutes with the online compiler\n" 311 | "\n" 312 | "We also provide an online development environment for mros2-mbed. \n" 313 | "By using the following Codes on Keil Studio Cloud (a.k.a Mbed Online Complier), you can try out the power of mros2 just in 5 minute. (we wish :D\n" 314 | "\n" 315 | "- example application:\n" 316 | " - [mbed-os-example-mros2 (echoreply_string)](https://os.mbed.com/users/smoritaemb/code/mbed-os-example-mros2/)\n" 317 | " - [mbed-os-example-mros2-pub-twist (pub-twist)](https://os.mbed.com/users/smoritaemb/code/example-mbed-mros2-pub-twist/)\n" 318 | " - [mbed-os-example-mros2-sub-pose (sub-pose)](https://os.mbed.com/users/smoritaemb/code/example-mbed-mros2-sub-pose/)\n" 319 | "- [mbed-mros2 (core library for mros2-mbed)](https://os.mbed.com/users/smoritaemb/code/mbed-mros2/)\n" 320 | "\n" 321 | "Please feel free to let us know in [Issues on this repository](https://github.com/mROS-base/mros2-mbed/issues) if you have any troubles or causes.\n" 322 | "\n" 323 | "## Submodules and Licenses\n" 324 | "\n" 325 | "The source code of this repository itself is published under [Apache License 2.0](https://github.com/mROS-base/mros2/blob/main/LICENSE). \n" 326 | "Please note that this repository contains the following stacks as the submodules, and also check their Licenses.\n" 327 | "\n" 328 | "- [mros2](https://github.com/mROS-base/mros2): the pub/sub APIs compatible with ROS 2 Rclcpp\n" 329 | " - [embeddedRTPS](https://github.com/mROS-base/embeddedRTPS): RTPS communication layer (including lwIP and Micro-CDR)\n" 330 | "- [Mbed OS 6](https://github.com/ARMmbed/mbed-os): an open source embedded operating system designed specifically for the \"things\" in the Internet of Things\n" 331 | "\n" 332 | -------------------------------------------------------------------------------- /workspace/pub_long_string_sub_crc/main/pub_long_string_sub_crc.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | 65;6800;1c * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "std_msgs/msg/string.hpp" 20 | #include "std_msgs/msg/u_int32.hpp" 21 | 22 | 23 | // imported from 24 | // https://github.com/aeldidi/crc32/blob/master/src/crc32.c 25 | uint32_t 26 | crc32_for_byte(uint32_t byte) 27 | { 28 | const uint32_t polynomial = 0xEDB88320L; 29 | uint32_t result = byte; 30 | size_t i = 0; 31 | 32 | for (; i < 8; i++) { 33 | result = (result >> 1) ^ (result & 1) * polynomial; 34 | } 35 | return result; 36 | } 37 | 38 | uint32_t 39 | crc32(const void *input, size_t size) 40 | { 41 | const uint8_t *current = static_cast(input); 42 | uint32_t result = 0xFFFFFFFF; 43 | size_t i = 0; 44 | 45 | for (; i < size; i++) { 46 | result ^= current[i]; 47 | result = crc32_for_byte(result); 48 | } 49 | 50 | return ~result; 51 | } 52 | 53 | const char long_text[] = 54 | #include "long_text.txt" 55 | ; 56 | const size_t text_size = sizeof(long_text) / 4; 57 | 58 | void userCallback(std_msgs::msg::UInt32 *msg) 59 | { 60 | if (msg->data == crc32(long_text, text_size)) { 61 | MROS2_INFO("CRC is OK: 0x%0lx", msg->data); 62 | } else { 63 | MROS2_INFO("CRC is NG: 0x%0lx", msg->data); 64 | } 65 | } 66 | 67 | extern "C" void app_main(void) 68 | { 69 | /* connect to the network */ 70 | if (mros2_platform_network_connect()) 71 | { 72 | MROS2_INFO("successfully connect and setup network\r\n---"); 73 | } 74 | else 75 | { 76 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 77 | return; 78 | } 79 | 80 | MROS2_INFO("%s start!", MROS2_PLATFORM_NAME); 81 | MROS2_INFO("app name: pub_long_string_sub_crc"); 82 | 83 | mros2::init(0, NULL); 84 | MROS2_DEBUG("mROS 2 initialization is completed"); 85 | 86 | mros2::Node node = mros2::Node::create_node("mros2_node"); 87 | mros2::Publisher pub = node.create_publisher("to_linux", 1); 88 | mros2::Subscriber sub = node.create_subscription("to_stm", 10, userCallback); 89 | 90 | osDelay(100); 91 | MROS2_INFO("ready to pub/sub message\r\n---"); 92 | 93 | auto msg = std_msgs::msg::String(); 94 | 95 | while (1) 96 | { 97 | msg.data.resize(text_size); 98 | memcpy(reinterpret_cast(&msg.data[0]), 99 | long_text, text_size); 100 | 101 | MROS2_INFO("publishing message whose CRC(len=%d) is 0x%0lx", 102 | msg.data.size(), crc32(long_text, sizeof(long_text) / 4)); 103 | pub.publish(msg); 104 | 105 | osDelay(1000); 106 | } 107 | 108 | mros2::spin(); 109 | return; 110 | } 111 | -------------------------------------------------------------------------------- /workspace/pub_twist/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(pub_twist) -------------------------------------------------------------------------------- /workspace/pub_twist/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "pub_twist.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/pub_twist/main/pub_twist.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "geometry_msgs/msg/vector3.hpp" 20 | #include "geometry_msgs/msg/twist.hpp" 21 | 22 | 23 | extern "C" void app_main(void) 24 | { 25 | /* connect to the network */ 26 | if (mros2_platform_network_connect()) 27 | { 28 | MROS2_INFO("successfully connect and setup network\r\n---"); 29 | } 30 | else 31 | { 32 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 33 | return; 34 | } 35 | 36 | MROS2_INFO("mbed mros2 start!"); 37 | MROS2_INFO("app name: pub_twist"); 38 | 39 | mros2::init(0, NULL); 40 | MROS2_DEBUG("mROS 2 initialization is completed"); 41 | 42 | mros2::Node node = mros2::Node::create_node("mros2_node"); 43 | mros2::Publisher pub = node.create_publisher("cmd_vel", 10); 44 | osDelay(100); 45 | MROS2_INFO("ready to pub/sub message\r\n---"); 46 | 47 | geometry_msgs::msg::Vector3 linear; 48 | geometry_msgs::msg::Vector3 angular; 49 | geometry_msgs::msg::Twist twist; 50 | 51 | auto publish_count = 0; 52 | while (1) 53 | { 54 | linear.x = publish_count/1.0; 55 | linear.y = publish_count/1.0; 56 | linear.z = publish_count/1.0; 57 | angular.x = publish_count/1.0; 58 | angular.y = publish_count/1.0; 59 | angular.z = publish_count/1.0; 60 | twist.linear = linear; 61 | twist.angular = angular; 62 | MROS2_INFO("publishing Twist msg!!"); 63 | pub.publish(twist); 64 | publish_count++; 65 | osDelay(1000); 66 | } 67 | 68 | mros2::spin(); 69 | return; 70 | } -------------------------------------------------------------------------------- /workspace/sub_pose/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(sub_pose) -------------------------------------------------------------------------------- /workspace/sub_pose/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "sub_pose.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/sub_pose/main/sub_pose.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "geometry_msgs/msg/pose.hpp" 20 | 21 | 22 | void userCallback(geometry_msgs::msg::Pose *msg) 23 | { 24 | MROS2_INFO("subscribed Pose msg!!"); 25 | } 26 | 27 | extern "C" void app_main(void) 28 | { 29 | /* connect to the network */ 30 | if (mros2_platform_network_connect()) 31 | { 32 | MROS2_INFO("successfully connect and setup network\r\n---"); 33 | } 34 | else 35 | { 36 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 37 | return; 38 | } 39 | 40 | MROS2_INFO("mbed mros2 start!"); 41 | MROS2_INFO("app name: sub_pose"); 42 | 43 | mros2::init(0, NULL); 44 | MROS2_DEBUG("mROS 2 initialization is completed"); 45 | 46 | mros2::Node node = mros2::Node::create_node("sub_pose"); 47 | mros2::Subscriber sub = node.create_subscription("cmd_vel", 10, userCallback); 48 | osDelay(100); 49 | MROS2_INFO("ready to pub/sub message\r\n---"); 50 | 51 | mros2::spin(); 52 | return; 53 | } -------------------------------------------------------------------------------- /workspace/sub_uint16/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS ../..) 6 | add_compile_options(-w) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(sub_uint16) -------------------------------------------------------------------------------- /workspace/sub_uint16/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "sub_uint16.cpp" 2 | INCLUDE_DIRS "." 3 | PRIV_REQUIRES "mros2-esp32") 4 | -------------------------------------------------------------------------------- /workspace/sub_uint16/main/sub_uint16.cpp: -------------------------------------------------------------------------------- 1 | /* mros2 example 2 | * Copyright (c) 2023 mROS-base 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mros2.h" 18 | #include "mros2-platform.h" 19 | #include "std_msgs/msg/u_int16.hpp" 20 | 21 | 22 | void userCallback(std_msgs::msg::UInt16 *msg) 23 | { 24 | MROS2_INFO("subscribed msg: '%d'", msg->data); 25 | } 26 | 27 | extern "C" void app_main(void) 28 | { 29 | /* connect to the network */ 30 | if (mros2_platform_network_connect()) 31 | { 32 | MROS2_INFO("successfully connect and setup network\r\n---"); 33 | } 34 | else 35 | { 36 | MROS2_ERROR("failed to connect and setup network! aborting,,,"); 37 | return; 38 | } 39 | 40 | MROS2_INFO("mbed mros2 start!"); 41 | MROS2_INFO("app name: sub_uint16"); 42 | 43 | mros2::init(0, NULL); 44 | MROS2_DEBUG("mROS 2 initialization is completed"); 45 | 46 | mros2::Node node = mros2::Node::create_node("mros2_node"); 47 | mros2::Subscriber sub = node.create_subscription("to_stm", 10, userCallback); 48 | osDelay(100); 49 | MROS2_INFO("ready to pub/sub message\r\n---"); 50 | 51 | mros2::spin(); 52 | return; 53 | } --------------------------------------------------------------------------------