├── .codespellrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── stale.yml └── workflows │ ├── auto-github-actions.yml │ ├── check-arduino.yml │ ├── report-size-deltas.yml │ └── spell-check.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Packages_Patches └── arduino │ └── hardware │ └── mbed_portenta │ ├── 2.4.1 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ ├── libraries │ │ └── SocketWrapper │ │ │ └── src │ │ │ ├── MbedUdp.cpp │ │ │ └── MbedUdp.h │ └── portenta_post_install.sh │ ├── 2.5.2 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ ├── libraries │ │ └── SocketWrapper │ │ │ └── src │ │ │ ├── MbedUdp.cpp │ │ │ └── MbedUdp.h │ └── portenta_post_install.sh │ ├── 2.6.1 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ ├── libraries │ │ └── SocketWrapper │ │ │ └── src │ │ │ ├── MbedUdp.cpp │ │ │ └── MbedUdp.h │ └── portenta_post_install.sh │ ├── 2.7.2 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ └── portenta_post_install.sh │ ├── 2.8.0 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ └── portenta_post_install.sh │ ├── 3.0.0 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ └── portenta_post_install.sh │ ├── 3.0.1 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ └── portenta_post_install.sh │ ├── 3.1.1 │ ├── cores │ │ └── arduino │ │ │ └── mbed │ │ │ └── connectivity │ │ │ └── lwipstack │ │ │ └── include │ │ │ └── lwipstack │ │ │ └── lwipopts.h │ └── portenta_post_install.sh │ ├── 3.3.0 │ └── portenta_post_install.sh │ └── 3.4.1 │ └── portenta_post_install.sh ├── README.md ├── changelog.md ├── examples ├── Argument_None │ └── Argument_None.ino ├── Change_Interval │ └── Change_Interval.ino ├── ISR_16_Timers_Array │ └── ISR_16_Timers_Array.ino ├── ISR_16_Timers_Array_Complex │ └── ISR_16_Timers_Array_Complex.ino ├── PWM │ ├── PWM_Multi │ │ └── PWM_Multi.ino │ └── PWM_Multi_Args │ │ └── PWM_Multi_Args.ino ├── SwitchDebounce │ └── SwitchDebounce.ino ├── TimerInterruptLEDDemo │ └── TimerInterruptLEDDemo.ino ├── TimerInterruptTest │ └── TimerInterruptTest.ino └── multiFileProject │ ├── multiFileProject.cpp │ ├── multiFileProject.h │ └── multiFileProject.ino ├── keywords.txt ├── library.json ├── library.properties ├── platformio └── platformio.ini ├── src ├── Portenta_H7_ISR_Timer-Impl.h ├── Portenta_H7_ISR_Timer.h ├── Portenta_H7_ISR_Timer.hpp ├── Portenta_H7_TimerInterrupt.h ├── TimerInterrupt_Generic_Debug.h └── stm32 │ ├── HardwareTimer.cpp │ ├── HardwareTimer.h │ ├── timer.c │ └── timer.h └── utils ├── astyle_library.conf └── restyle.sh /.codespellrc: -------------------------------------------------------------------------------- 1 | # See: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: 4 | ignore-words-list = , 5 | check-filenames = 6 | check-hidden = 7 | skip = ./.git,./src,./examples,./Packages_Patches,./LibraryPatches 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the bug 11 | 12 | A clear and concise description of what the bug is. 13 | 14 | ### Steps to Reproduce 15 | 16 | Steps to reproduce the behavior. Including the [MRE](https://stackoverflow.com/help/minimal-reproducible-example) sketches 17 | 18 | ### Expected behavior 19 | 20 | A clear and concise description of what you expected to happen. 21 | 22 | ### Actual behavior 23 | 24 | A clear and concise description of what you expected to happen. 25 | 26 | ### Debug and AT-command log (if applicable) 27 | 28 | A clear and concise description of what you expected to happen. 29 | 30 | ### Screenshots 31 | 32 | If applicable, add screenshots to help explain your problem. 33 | 34 | ### Information 35 | 36 | Please ensure to specify the following: 37 | 38 | * Arduino IDE version (e.g. 1.8.13) or Platform.io version 39 | * `ESP8266`,`ESP32` or `STM32` Core Version (e.g. ESP8266 core v2.7.4, ESP32 v1.0.5 or STM32 v1.9.0) 40 | * Contextual information (e.g. what you were trying to achieve) 41 | * Simplest possible steps to reproduce 42 | * Anything that might be relevant in your opinion, such as: 43 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 44 | * Network configuration 45 | 46 | ### Example 47 | 48 | ``` 49 | Arduino IDE version: 1.8.13 50 | ESP32 Core Version 1.0.5 51 | OS: Ubuntu 20.04 LTS 52 | Linux xy-Inspiron-3593 5.4.0-66-generic #74-Ubuntu SMP Wed Jan 27 22:54:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux 53 | 54 | Context: 55 | I encountered an endless loop while trying to connect to Local WiFi. 56 | 57 | Steps to reproduce: 58 | 1. ... 59 | 2. ... 60 | 3. ... 61 | 4. ... 62 | ``` 63 | 64 | ### Additional context 65 | 66 | Add any other context about the problem here. 67 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Is your feature request related to a problem? Please describe. 11 | 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | 14 | ### Describe the solution you'd like 15 | 16 | A clear and concise description of what you want to happen. 17 | 18 | ### Describe alternatives you've considered 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | ### Additional context 22 | 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file 2 | version: 2 3 | 4 | updates: 5 | # Configure check for outdated GitHub Actions actions in workflows. 6 | # See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot 7 | - package-ecosystem: github-actions 8 | directory: / # Check the repository's workflows under /.github/workflows/ 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | daysUntilStale: 60 4 | daysUntilClose: 14 5 | limitPerRun: 30 6 | staleLabel: stale 7 | exemptLabels: 8 | - pinned 9 | - security 10 | - "to be implemented" 11 | - "for reference" 12 | - "move to PR" 13 | - "enhancement" 14 | 15 | only: issues 16 | onlyLabels: [] 17 | exemptProjects: false 18 | exemptMilestones: false 19 | exemptAssignees: false 20 | 21 | markComment: > 22 | [STALE_SET] This issue has been automatically marked as stale because it has not had 23 | recent activity. It will be closed in 14 days if no further activity occurs. Thank you 24 | for your contributions. 25 | 26 | unmarkComment: > 27 | [STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it opening the future. 28 | 29 | closeComment: > 30 | [STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/auto-github-actions.yml: -------------------------------------------------------------------------------- 1 | name: auto-github-actions 2 | on: [push] 3 | jobs: 4 | check-bats-version: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v3 8 | - uses: actions/setup-node@v3 9 | with: 10 | node-version: '14' 11 | - run: npm install -g bats 12 | - run: bats -v 13 | -------------------------------------------------------------------------------- /.github/workflows/check-arduino.yml: -------------------------------------------------------------------------------- 1 | name: Check Arduino 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | pull_request: 7 | schedule: 8 | # Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint. 9 | - cron: "0 8 * * TUE" 10 | workflow_dispatch: 11 | repository_dispatch: 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | 21 | - name: Arduino Lint 22 | uses: arduino/arduino-lint-action@v1 23 | with: 24 | compliance: specification 25 | library-manager: update 26 | # Always use this setting for official repositories. Remove for 3rd party projects. 27 | official: true 28 | project-type: library 29 | -------------------------------------------------------------------------------- /.github/workflows/report-size-deltas.yml: -------------------------------------------------------------------------------- 1 | name: Report Size Deltas 2 | 3 | on: 4 | schedule: 5 | - cron: '*/5 * * * *' 6 | 7 | jobs: 8 | report: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Comment size deltas reports to PRs 13 | uses: arduino/report-size-deltas@v1 14 | with: 15 | # The name of the workflow artifact created by the "Compile Examples" workflow 16 | sketches-reports-source: sketches-reports 17 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | name: Spell Check 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | # run every Tuesday at 3 AM UTC 8 | - cron: "0 3 * * 2" 9 | workflow_dispatch: 10 | repository_dispatch: 11 | 12 | jobs: 13 | spellcheck: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | 20 | # See: https://github.com/codespell-project/actions-codespell/blob/master/README.md 21 | - name: Spell check 22 | uses: codespell-project/actions-codespell@master 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to Portenta_H7_TimerInterrupt 2 | 3 | ### Reporting Bugs 4 | 5 | Please report bugs in [Portenta_H7_TimerInterrupt Issues](https://github.com/khoih-prog/Portenta_H7_TimerInterrupt/issues) if you find them. 6 | 7 | However, before reporting a bug please check through the following: 8 | 9 | * [Existing Open Issues](https://github.com/khoih-prog/Portenta_H7_TimerInterrupt/issues) - someone might have already encountered this. 10 | 11 | If you don't find anything, please [open a new issue](https://github.com/khoih-prog/Portenta_H7_TimerInterrupt/issues/new). 12 | 13 | ### How to submit a bug report 14 | 15 | Please ensure to specify the following: 16 | 17 | * Arduino IDE version (e.g. 1.8.19) or Platform.io version 18 | * `ArduinoCore-mbed` Core Version (e.g. `ArduinoCore-mbed` mbed_portenta core v3.4.1) 19 | * `Portenta_H7` Board type (e.g. Portenta_H7 Rev2 ABX00042, etc.) 20 | * Contextual information (e.g. what you were trying to achieve) 21 | * Simplest possible steps to reproduce 22 | * Anything that might be relevant in your opinion, such as: 23 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 24 | * Network configuration 25 | 26 | 27 | ### Example 28 | 29 | ``` 30 | Arduino IDE version: 1.8.19 31 | `ArduinoCore-mbed` mbed_portenta core v3.4.1 32 | Portenta_H7 Rev2 ABX00042 33 | OS: Ubuntu 20.04 LTS 34 | Linux xy-Inspiron-3593 5.15.0-53-generic #59~20.04.1-Ubuntu SMP Thu Oct 20 15:10:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux 35 | 36 | Context: 37 | I encountered a crash while using this library 38 | Steps to reproduce: 39 | 1. ... 40 | 2. ... 41 | 3. ... 42 | 4. ... 43 | ``` 44 | 45 | ### Additional context 46 | 47 | Add any other context about the problem here. 48 | 49 | --- 50 | 51 | ### Sending Feature Requests 52 | 53 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. 54 | 55 | There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/Portenta_H7_TimerInterrupt/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. 56 | 57 | --- 58 | 59 | ### Sending Pull Requests 60 | 61 | Pull Requests with changes and fixes are also welcome! 62 | 63 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux) 64 | 65 | 1. Change directory to the library GitHub 66 | 67 | ``` 68 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/Portenta_H7_TimerInterrupt_GitHub/ 69 | xy@xy-Inspiron-3593:~/Arduino/xy/Portenta_H7_TimerInterrupt_GitHub$ 70 | ``` 71 | 72 | 2. Issue astyle command 73 | 74 | ``` 75 | xy@xy-Inspiron-3593:~/Arduino/xy/Portenta_H7_TimerInterrupt_GitHub$ bash utils/restyle.sh 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Khoi Hoang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.4.1/cores/arduino/mbed/connectivity/lwipstack/include/lwipstack/lwipopts.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012 mbed.org, MIT License 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 7 | * furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or 10 | * substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | #ifndef LWIPOPTS_H 20 | #define LWIPOPTS_H 21 | 22 | // Workaround for Linux timeval 23 | #if defined (TOOLCHAIN_GCC) 24 | #define LWIP_TIMEVAL_PRIVATE 0 25 | #include 26 | #endif 27 | #include "nsapi_types.h" 28 | #include "mbed_retarget.h" 29 | 30 | // KH fix 31 | #include 32 | ///////////////////////// 33 | 34 | // Operating System 35 | #define NO_SYS 0 36 | 37 | #if !MBED_CONF_LWIP_IPV4_ENABLED && !MBED_CONF_LWIP_IPV6_ENABLED 38 | #error "Either IPv4 or IPv6 must be enabled." 39 | #endif 40 | 41 | #define LWIP_IPV4 MBED_CONF_LWIP_IPV4_ENABLED 42 | 43 | #define LWIP_IPV6 MBED_CONF_LWIP_IPV6_ENABLED 44 | 45 | #define LWIP_PROVIDE_ERRNO 0 46 | 47 | // On dual stack configuration how long to wait for both or preferred stack 48 | // addresses before completing bring up. 49 | #if LWIP_IPV4 && LWIP_IPV6 50 | #if MBED_CONF_LWIP_ADDR_TIMEOUT_MODE 51 | #define BOTH_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 52 | #define PREF_ADDR_TIMEOUT 0 53 | #else 54 | #define PREF_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 55 | #define BOTH_ADDR_TIMEOUT 0 56 | #endif 57 | #else 58 | #define PREF_ADDR_TIMEOUT 0 59 | #define BOTH_ADDR_TIMEOUT 0 60 | #endif 61 | 62 | 63 | #define DHCP_TIMEOUT MBED_CONF_LWIP_DHCP_TIMEOUT 64 | 65 | #define LINK_TIMEOUT 60 66 | 67 | #define PREF_IPV4 1 68 | #define PREF_IPV6 2 69 | 70 | #if MBED_CONF_LWIP_IP_VER_PREF == 6 71 | #define IP_VERSION_PREF PREF_IPV6 72 | #elif MBED_CONF_LWIP_IP_VER_PREF == 4 73 | #define IP_VERSION_PREF PREF_IPV4 74 | #else 75 | #error "Either IPv4 or IPv6 must be preferred." 76 | #endif 77 | 78 | #undef LWIP_DEBUG 79 | #if MBED_CONF_LWIP_DEBUG_ENABLED 80 | #define LWIP_DEBUG 1 81 | #endif 82 | 83 | #if NO_SYS == 0 84 | #include "cmsis_os2.h" 85 | 86 | #define SYS_LIGHTWEIGHT_PROT 1 87 | 88 | #define LWIP_RAW MBED_CONF_LWIP_RAW_SOCKET_ENABLED 89 | 90 | #define MEMP_NUM_TCPIP_MSG_INPKT MBED_CONF_LWIP_MEMP_NUM_TCPIP_MSG_INPKT 91 | 92 | // Thread stacks use 8-byte alignment 93 | #define LWIP_ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) 94 | 95 | #ifdef LWIP_DEBUG 96 | // For LWIP debug, double the stack 97 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE*2, 8) 98 | #elif MBED_DEBUG 99 | // When debug is enabled on the build increase stack 25 percent 100 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE + MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE / 4, 8) 101 | #else 102 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE, 8) 103 | #endif 104 | 105 | // Thread priority (osPriorityNormal by default) 106 | #define TCPIP_THREAD_PRIO (MBED_CONF_LWIP_TCPIP_THREAD_PRIORITY) 107 | 108 | #ifdef LWIP_DEBUG 109 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE*2, 8) 110 | #else 111 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE, 8) 112 | #endif 113 | 114 | #define MEMP_NUM_SYS_TIMEOUT 16 115 | 116 | #define sys_msleep(ms) sys_msleep(ms) 117 | 118 | #endif 119 | 120 | // 32-bit alignment 121 | #define MEM_ALIGNMENT 4 122 | 123 | #define LWIP_RAM_HEAP_POINTER lwip_ram_heap 124 | 125 | // Number of simultaneously queued TCP segments. 126 | #define MEMP_NUM_TCP_SEG MBED_CONF_LWIP_MEMP_NUM_TCP_SEG 127 | 128 | // TCP Maximum segment size. 129 | #define TCP_MSS MBED_CONF_LWIP_TCP_MSS 130 | 131 | // TCP sender buffer space (bytes). 132 | #define TCP_SND_BUF MBED_CONF_LWIP_TCP_SND_BUF 133 | 134 | // TCP sender buffer space (bytes). 135 | #define TCP_WND MBED_CONF_LWIP_TCP_WND 136 | 137 | #define TCP_MAXRTX MBED_CONF_LWIP_TCP_MAXRTX 138 | 139 | #define TCP_SYNMAXRTX MBED_CONF_LWIP_TCP_SYNMAXRTX 140 | 141 | // Number of pool pbufs. 142 | // Each requires 684 bytes of RAM (if MSS=536 and PBUF_POOL_BUFSIZE defaulting to be based on MSS) 143 | #define PBUF_POOL_SIZE MBED_CONF_LWIP_PBUF_POOL_SIZE 144 | 145 | #ifdef MBED_CONF_LWIP_PBUF_POOL_BUFSIZE 146 | #undef PBUF_POOL_BUFSIZE 147 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_LWIP_PBUF_POOL_BUFSIZE) 148 | #else 149 | #ifndef PBUF_POOL_BUFSIZE 150 | #if LWIP_IPV6 151 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 152 | #elif LWIP_IPV4 153 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+20+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 154 | #endif 155 | #endif 156 | #endif 157 | 158 | #define MEM_SIZE MBED_CONF_LWIP_MEM_SIZE 159 | 160 | // One tcp_pcb_listen is needed for each TCP server. 161 | // Each requires 72 bytes of RAM. 162 | #define MEMP_NUM_TCP_PCB_LISTEN MBED_CONF_LWIP_TCP_SERVER_MAX 163 | 164 | // One is tcp_pcb needed for each TCPSocket. 165 | // Each requires 196 bytes of RAM. 166 | #define MEMP_NUM_TCP_PCB MBED_CONF_LWIP_TCP_SOCKET_MAX 167 | 168 | // One udp_pcb is needed for each UDPSocket. 169 | // Each requires 84 bytes of RAM (total rounded to multiple of 512). 170 | #define MEMP_NUM_UDP_PCB MBED_CONF_LWIP_UDP_SOCKET_MAX 171 | 172 | // Number of non-pool pbufs. 173 | // Each requires 92 bytes of RAM. 174 | #define MEMP_NUM_PBUF MBED_CONF_LWIP_NUM_PBUF 175 | 176 | // Each netbuf requires 64 bytes of RAM. 177 | #define MEMP_NUM_NETBUF MBED_CONF_LWIP_NUM_NETBUF 178 | 179 | // One netconn is needed for each UDPSocket or TCPSocket. 180 | // Each requires 236 bytes of RAM (total rounded to multiple of 512). 181 | #define MEMP_NUM_NETCONN MBED_CONF_LWIP_SOCKET_MAX 182 | 183 | #if MBED_CONF_LWIP_TCP_ENABLED 184 | #define LWIP_TCP 1 185 | #define TCP_OVERSIZE 0 186 | #define LWIP_TCP_KEEPALIVE 1 187 | 188 | #define TCP_CLOSE_TIMEOUT MBED_CONF_LWIP_TCP_CLOSE_TIMEOUT 189 | 190 | #else 191 | #define LWIP_TCP 0 192 | #endif 193 | 194 | #define LWIP_DNS 1 195 | // Only DNS address storage is enabled 196 | #define LWIP_FULL_DNS 0 197 | #define LWIP_SOCKET 0 198 | 199 | #define SO_REUSE 1 200 | 201 | // Support Multicast 202 | #include "stdlib.h" 203 | #define LWIP_IGMP LWIP_IPV4 204 | #define LWIP_RAND() lwip_get_random() 205 | 206 | #define LWIP_COMPAT_SOCKETS 0 207 | #define LWIP_POSIX_SOCKETS_IO_NAMES 0 208 | 209 | #define LWIP_BROADCAST_PING 1 210 | 211 | // Fragmentation on, as per IPv4 default 212 | #define LWIP_IPV6_FRAG LWIP_IPV6 213 | 214 | // Queuing, default is "disabled", as per IPv4 default (so actually queues 1) 215 | #define LWIP_ND6_QUEUEING MBED_CONF_ND6_QUEUEING 216 | 217 | // Debug Options 218 | #define NETIF_DEBUG LWIP_DBG_OFF 219 | #define PBUF_DEBUG LWIP_DBG_OFF 220 | #define API_LIB_DEBUG LWIP_DBG_OFF 221 | #define API_MSG_DEBUG LWIP_DBG_OFF 222 | #define SOCKETS_DEBUG LWIP_DBG_OFF 223 | #define ICMP_DEBUG LWIP_DBG_OFF 224 | #define IGMP_DEBUG LWIP_DBG_OFF 225 | #define INET_DEBUG LWIP_DBG_OFF 226 | #define IP_DEBUG LWIP_DBG_OFF 227 | #define IP_REASS_DEBUG LWIP_DBG_OFF 228 | #define RAW_DEBUG LWIP_DBG_OFF 229 | #define MEM_DEBUG LWIP_DBG_OFF 230 | #define MEMP_DEBUG LWIP_DBG_OFF 231 | #define SYS_DEBUG LWIP_DBG_OFF 232 | #define TIMERS_DEBUG LWIP_DBG_OFF 233 | #define TCP_DEBUG LWIP_DBG_OFF 234 | #define TCP_INPUT_DEBUG LWIP_DBG_OFF 235 | #define TCP_FR_DEBUG LWIP_DBG_OFF 236 | #define TCP_RTO_DEBUG LWIP_DBG_OFF 237 | #define TCP_CWND_DEBUG LWIP_DBG_OFF 238 | #define TCP_WND_DEBUG LWIP_DBG_OFF 239 | #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 240 | #define TCP_RST_DEBUG LWIP_DBG_OFF 241 | #define TCP_QLEN_DEBUG LWIP_DBG_OFF 242 | #define UDP_DEBUG LWIP_DBG_OFF 243 | #define TCPIP_DEBUG LWIP_DBG_OFF 244 | #define SLIP_DEBUG LWIP_DBG_OFF 245 | #define DHCP_DEBUG LWIP_DBG_OFF 246 | #define AUTOIP_DEBUG LWIP_DBG_OFF 247 | #define DNS_DEBUG LWIP_DBG_OFF 248 | #define IP6_DEBUG LWIP_DBG_OFF 249 | 250 | #define ETHARP_DEBUG LWIP_DBG_OFF 251 | #define UDP_LPC_EMAC LWIP_DBG_OFF 252 | 253 | #ifdef LWIP_DEBUG 254 | #define MEMP_OVERFLOW_CHECK 1 255 | #define MEMP_SANITY_CHECK 1 256 | #define LWIP_DBG_TYPES_ON LWIP_DBG_ON 257 | #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL 258 | #else 259 | #define LWIP_NOASSERT 1 260 | #define LWIP_STATS 0 261 | #endif 262 | 263 | #define TRACE_TO_ASCII_HEX_DUMP 0 264 | 265 | #define LWIP_PLATFORM_BYTESWAP 1 266 | 267 | #define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 268 | 269 | // Interface type configuration 270 | 271 | #if MBED_CONF_LWIP_ETHERNET_ENABLED 272 | #define LWIP_ARP 1 273 | #define LWIP_ETHERNET 1 274 | #define LWIP_DHCP LWIP_IPV4 275 | #else 276 | #define LWIP_ARP 0 277 | #define LWIP_ETHERNET 0 278 | #endif // MBED_CONF_LWIP_ETHERNET_ENABLED 279 | 280 | #if MBED_CONF_LWIP_L3IP_ENABLED 281 | #define LWIP_L3IP 1 282 | #else 283 | #define LWIP_L3IP 0 284 | #endif 285 | 286 | //Maximum size of network interface name 287 | #define INTERFACE_NAME_MAX_SIZE NSAPI_INTERFACE_NAME_MAX_SIZE 288 | // Note generic macro name used rather than MBED_CONF_LWIP_PPP_ENABLED 289 | // to allow users like PPPCellularInterface to detect that nsapi_ppp.h is available. 290 | 291 | // Enable PPP for now either from lwIP PPP configuration (obsolete) or from PPP service configuration 292 | #if MBED_CONF_PPP_ENABLED || MBED_CONF_LWIP_PPP_ENABLED 293 | 294 | #define PPP_SUPPORT 1 295 | 296 | #if MBED_CONF_PPP_IPV4_ENABLED || MBED_CONF_LWIP_IPV4_ENABLED 297 | #define LWIP 0x11991199 298 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV4_ENABLED 299 | #error LWIP: IPv4 PPP enabled but not IPv4 300 | #endif 301 | #undef LWIP 302 | #define PPP_IPV4_SUPPORT 1 303 | #endif 304 | 305 | #if MBED_CONF_PPP_IPV6_ENABLED || MBED_CONF_LWIP_IPV6_ENABLED 306 | #define LWIP 0x11991199 307 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV6_ENABLED 308 | #error LWIP: IPv6 PPP enabled but not IPv6 309 | #endif 310 | #undef LWIP 311 | #define PPP_IPV6_SUPPORT 1 312 | // Later to be dynamic for use for multiple interfaces 313 | #define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 314 | #endif 315 | 316 | #endif 317 | 318 | #define LWIP_NETBUF_RECVINFO MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED 319 | 320 | // Make sure we default these to off, so 321 | // LWIP doesn't default to on 322 | #ifndef LWIP_ARP 323 | #define LWIP_ARP 0 324 | #endif 325 | 326 | // Checksum-on-copy disabled due to https://savannah.nongnu.org/bugs/?50914 327 | #define LWIP_CHECKSUM_ON_COPY 0 328 | 329 | #define LWIP_NETIF_HOSTNAME 1 330 | #define LWIP_NETIF_STATUS_CALLBACK 1 331 | #define LWIP_NETIF_LINK_CALLBACK 1 332 | 333 | #define DNS_TABLE_SIZE 2 334 | #define DNS_MAX_NAME_LENGTH 128 335 | 336 | #include "lwip_random.h" 337 | #include "lwip_tcp_isn.h" 338 | #define LWIP_HOOK_TCP_ISN lwip_hook_tcp_isn 339 | #ifdef MBEDTLS_MD5_C 340 | #define LWIP_USE_EXTERNAL_MBEDTLS 1 341 | #else 342 | #define LWIP_USE_EXTERNAL_MBEDTLS 0 343 | #endif 344 | 345 | #define LWIP_ND6_RDNSS_MAX_DNS_SERVERS MBED_CONF_LWIP_ND6_RDNSS_MAX_DNS_SERVERS 346 | 347 | #endif /* LWIPOPTS_H_ */ 348 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.4.1/libraries/SocketWrapper/src/MbedUdp.cpp: -------------------------------------------------------------------------------- 1 | #include "MbedUdp.h" 2 | 3 | arduino::MbedUDP::MbedUDP() { 4 | _packet_buffer = new uint8_t[WIFI_UDP_BUFFER_SIZE]; 5 | _current_packet = NULL; 6 | _current_packet_size = 0; 7 | // if this allocation fails then ::begin will fail 8 | } 9 | 10 | arduino::MbedUDP::~MbedUDP() { 11 | delete[] _packet_buffer; 12 | } 13 | 14 | uint8_t arduino::MbedUDP::begin(uint16_t port) { 15 | // success = 1, fail = 0 16 | 17 | nsapi_error_t rt = _socket.open(getNetwork()); 18 | if (rt != NSAPI_ERROR_OK) { 19 | return 0; 20 | } 21 | 22 | if (_socket.bind(port) < 0) { 23 | return 0; //Failed to bind UDP Socket to port 24 | } 25 | 26 | if (!_packet_buffer) { 27 | return 0; 28 | } 29 | 30 | _socket.set_blocking(false); 31 | _socket.set_timeout(0); 32 | 33 | return 1; 34 | } 35 | 36 | uint8_t arduino::MbedUDP::beginMulticast(IPAddress ip, uint16_t port) { 37 | // success = 1, fail = 0 38 | if (begin(port) != 1) { 39 | return 0; 40 | } 41 | 42 | SocketAddress socketAddress = SocketHelpers::socketAddressFromIpAddress(ip, port); 43 | 44 | if (_socket.join_multicast_group(socketAddress) != NSAPI_ERROR_OK) { 45 | printf("Error joining the multicast group\n"); 46 | return 0; 47 | } 48 | 49 | return 1; 50 | } 51 | 52 | void arduino::MbedUDP::stop() { 53 | _socket.close(); 54 | } 55 | 56 | int arduino::MbedUDP::beginPacket(IPAddress ip, uint16_t port) { 57 | _host = SocketHelpers::socketAddressFromIpAddress(ip, port); 58 | //If IP is null and port is 0 the initialization failed 59 | txBuffer.clear(); 60 | return (_host.get_ip_address() == nullptr && _host.get_port() == 0) ? 0 : 1; 61 | } 62 | 63 | int arduino::MbedUDP::beginPacket(const char *host, uint16_t port) { 64 | _host = SocketAddress(host, port); 65 | txBuffer.clear(); 66 | getNetwork()->gethostbyname(host, &_host); 67 | //If IP is null and port is 0 the initialization failed 68 | return (_host.get_ip_address() == nullptr && _host.get_port() == 0) ? 0 : 1; 69 | } 70 | 71 | int arduino::MbedUDP::endPacket() { 72 | _socket.set_blocking(true); 73 | _socket.set_timeout(1000); 74 | 75 | size_t size = txBuffer.available(); 76 | uint8_t buffer[size]; 77 | for (int i = 0; i < size; i++) { 78 | buffer[i] = txBuffer.read_char(); 79 | } 80 | 81 | nsapi_size_or_error_t ret = _socket.sendto(_host, buffer, size); 82 | _socket.set_blocking(false); 83 | _socket.set_timeout(0); 84 | if (ret < 0) { 85 | return 0; 86 | } 87 | return size; 88 | } 89 | 90 | // Write a single byte into the packet 91 | size_t arduino::MbedUDP::write(uint8_t byte) { 92 | return write(&byte, 1); 93 | } 94 | 95 | // Write size bytes from buffer into the packet 96 | size_t arduino::MbedUDP::write(const uint8_t *buffer, size_t size) { 97 | for (int i = 0; i _packet_buffer + _current_packet_size) { 146 | // try reading the next packet... 147 | if (parsePacket() > 0) { 148 | // if so, read first byte of next packet; 149 | return read(); 150 | } else { 151 | // no new data... not sure what to return here now 152 | return -1; 153 | } 154 | } 155 | 156 | return _current_packet[0]; 157 | } 158 | 159 | // Read up to len bytes from the current packet and place them into buffer 160 | // Returns the number of bytes read, or 0 if none are available 161 | int arduino::MbedUDP::read(unsigned char *buffer, size_t len) { 162 | // Q: does Arduino read() function handle fragmentation? I won't for now... 163 | if (_current_packet == NULL) { 164 | if (parsePacket() == 0) return 0; 165 | } 166 | 167 | // how much data do we have in the current packet? 168 | int offset = _current_packet - _packet_buffer; 169 | if (offset < 0) { 170 | return 0; 171 | } 172 | 173 | int max_bytes = _current_packet_size - offset; 174 | if (max_bytes < 0) { 175 | return 0; 176 | } 177 | 178 | // at the end of the packet? 179 | if (max_bytes == 0) { 180 | // try read next packet... 181 | if (parsePacket() > 0) { 182 | return read(buffer, len); 183 | } else { 184 | return 0; 185 | } 186 | } 187 | 188 | if (len > (size_t)max_bytes) len = max_bytes; 189 | 190 | // copy to target buffer 191 | memcpy(buffer, _current_packet, len); 192 | 193 | _current_packet += len; 194 | 195 | return len; 196 | } 197 | 198 | IPAddress arduino::MbedUDP::remoteIP() { 199 | nsapi_addr_t address = _remoteHost.get_addr(); 200 | return IPAddress(address.bytes[0], address.bytes[1], address.bytes[2], address.bytes[3]); 201 | } 202 | 203 | uint16_t arduino::MbedUDP::remotePort() { 204 | return _remoteHost.get_port(); 205 | } 206 | 207 | void arduino::MbedUDP::flush() { 208 | // TODO: a real check to ensure transmission has been completed 209 | } 210 | 211 | int arduino::MbedUDP::peek() { 212 | if (_current_packet_size < 1) { 213 | return -1; 214 | } 215 | 216 | return _current_packet[0]; 217 | } 218 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.4.1/libraries/SocketWrapper/src/MbedUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | MbedUdp.h - UDP implementation using mbed Sockets 3 | Copyright (c) 2021 Arduino SA. All right reserved. 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | This library is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | Lesser General Public License for more details. 12 | You should have received a copy of the GNU Lesser General Public 13 | License along with this library; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 15 | */ 16 | 17 | #ifndef MBEDUDP_H 18 | #define MBEDUDP_H 19 | 20 | #include "Arduino.h" 21 | #include "SocketHelpers.h" 22 | #include "api/Udp.h" 23 | 24 | #include "netsocket/SocketAddress.h" 25 | #include "netsocket/UDPSocket.h" 26 | 27 | #ifndef WIFI_UDP_BUFFER_SIZE 28 | #define WIFI_UDP_BUFFER_SIZE 508 29 | #endif 30 | 31 | namespace arduino { 32 | 33 | class MbedUDP : public UDP { 34 | private: 35 | UDPSocket _socket; // Mbed OS socket 36 | SocketAddress _host; // Host to be used to send data 37 | SocketAddress _remoteHost; // Remote host that sent incoming packets 38 | 39 | uint8_t* _packet_buffer; // Raw packet buffer (contains data we got from the UDPSocket) 40 | 41 | // The Arduino APIs allow you to iterate through this buffer, so we need to be able to iterate over the current packet 42 | // these two variables are used to cache the state of the current packet 43 | uint8_t* _current_packet; 44 | size_t _current_packet_size; 45 | 46 | RingBufferN txBuffer; 47 | 48 | protected: 49 | virtual NetworkInterface* getNetwork() = 0; 50 | 51 | public: 52 | MbedUDP(); // Constructor 53 | ~MbedUDP(); 54 | virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 55 | virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 if there are no sockets available to use 56 | virtual void stop(); // Finish with the UDP socket 57 | 58 | // Sending UDP packets 59 | 60 | // Start building up a packet to send to the remote host specific in ip and port 61 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 62 | virtual int beginPacket(IPAddress ip, uint16_t port); 63 | // Start building up a packet to send to the remote host specific in host and port 64 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 65 | virtual int beginPacket(const char* host, uint16_t port); 66 | // Finish off this packet and send it 67 | // Returns 1 if the packet was sent successfully, 0 if there was an error 68 | virtual int endPacket(); 69 | // Write a single byte into the packet 70 | virtual size_t write(uint8_t); 71 | // Write size bytes from buffer into the packet 72 | virtual size_t write(const uint8_t* buffer, size_t size); 73 | 74 | using Print::write; 75 | 76 | // Start processing the next available incoming packet 77 | // Returns the size of the packet in bytes, or 0 if no packets are available 78 | virtual int parsePacket(); 79 | // Number of bytes remaining in the current packet 80 | virtual int available(); 81 | // Read a single byte from the current packet 82 | virtual int read(); 83 | // Read up to len bytes from the current packet and place them into buffer 84 | // Returns the number of bytes read, or 0 if none are available 85 | virtual int read(unsigned char* buffer, size_t len); 86 | // Read up to len characters from the current packet and place them into buffer 87 | // Returns the number of characters read, or 0 if none are available 88 | virtual int read(char* buffer, size_t len) { 89 | return read((unsigned char*)buffer, len); 90 | }; 91 | // Return the next byte from the current packet without moving on to the next byte 92 | virtual int peek(); 93 | virtual void flush(); // Finish reading the current packet 94 | 95 | // Return the IP address of the host who sent the current incoming packet 96 | virtual IPAddress remoteIP(); 97 | // // Return the port of the host who sent the current incoming packet 98 | virtual uint16_t remotePort(); 99 | 100 | friend class MbedSocketClass; 101 | }; 102 | 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.4.1/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.5.2/cores/arduino/mbed/connectivity/lwipstack/include/lwipstack/lwipopts.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012 mbed.org, MIT License 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 7 | * furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or 10 | * substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | #ifndef LWIPOPTS_H 20 | #define LWIPOPTS_H 21 | 22 | // Workaround for Linux timeval 23 | #if defined (TOOLCHAIN_GCC) 24 | #define LWIP_TIMEVAL_PRIVATE 0 25 | #include 26 | #endif 27 | #include "nsapi_types.h" 28 | #include "mbed_retarget.h" 29 | 30 | // KH fix 31 | #include 32 | ///////////////////////// 33 | 34 | // Operating System 35 | #define NO_SYS 0 36 | 37 | #if !MBED_CONF_LWIP_IPV4_ENABLED && !MBED_CONF_LWIP_IPV6_ENABLED 38 | #error "Either IPv4 or IPv6 must be enabled." 39 | #endif 40 | 41 | #define LWIP_IPV4 MBED_CONF_LWIP_IPV4_ENABLED 42 | 43 | #define LWIP_IPV6 MBED_CONF_LWIP_IPV6_ENABLED 44 | 45 | #define LWIP_PROVIDE_ERRNO 0 46 | 47 | // On dual stack configuration how long to wait for both or preferred stack 48 | // addresses before completing bring up. 49 | #if LWIP_IPV4 && LWIP_IPV6 50 | #if MBED_CONF_LWIP_ADDR_TIMEOUT_MODE 51 | #define BOTH_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 52 | #define PREF_ADDR_TIMEOUT 0 53 | #else 54 | #define PREF_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 55 | #define BOTH_ADDR_TIMEOUT 0 56 | #endif 57 | #else 58 | #define PREF_ADDR_TIMEOUT 0 59 | #define BOTH_ADDR_TIMEOUT 0 60 | #endif 61 | 62 | 63 | #define DHCP_TIMEOUT MBED_CONF_LWIP_DHCP_TIMEOUT 64 | 65 | #define LINK_TIMEOUT 60 66 | 67 | #define PREF_IPV4 1 68 | #define PREF_IPV6 2 69 | 70 | #if MBED_CONF_LWIP_IP_VER_PREF == 6 71 | #define IP_VERSION_PREF PREF_IPV6 72 | #elif MBED_CONF_LWIP_IP_VER_PREF == 4 73 | #define IP_VERSION_PREF PREF_IPV4 74 | #else 75 | #error "Either IPv4 or IPv6 must be preferred." 76 | #endif 77 | 78 | #undef LWIP_DEBUG 79 | #if MBED_CONF_LWIP_DEBUG_ENABLED 80 | #define LWIP_DEBUG 1 81 | #endif 82 | 83 | #if NO_SYS == 0 84 | #include "cmsis_os2.h" 85 | 86 | #define SYS_LIGHTWEIGHT_PROT 1 87 | 88 | #define LWIP_RAW MBED_CONF_LWIP_RAW_SOCKET_ENABLED 89 | 90 | #define MEMP_NUM_TCPIP_MSG_INPKT MBED_CONF_LWIP_MEMP_NUM_TCPIP_MSG_INPKT 91 | 92 | // Thread stacks use 8-byte alignment 93 | #define LWIP_ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) 94 | 95 | #ifdef LWIP_DEBUG 96 | // For LWIP debug, double the stack 97 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE*2, 8) 98 | #elif MBED_DEBUG 99 | // When debug is enabled on the build increase stack 25 percent 100 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE + MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE / 4, 8) 101 | #else 102 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE, 8) 103 | #endif 104 | 105 | // Thread priority (osPriorityNormal by default) 106 | #define TCPIP_THREAD_PRIO (MBED_CONF_LWIP_TCPIP_THREAD_PRIORITY) 107 | 108 | #ifdef LWIP_DEBUG 109 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE*2, 8) 110 | #else 111 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE, 8) 112 | #endif 113 | 114 | #define MEMP_NUM_SYS_TIMEOUT 16 115 | 116 | #define sys_msleep(ms) sys_msleep(ms) 117 | 118 | #endif 119 | 120 | // 32-bit alignment 121 | #define MEM_ALIGNMENT 4 122 | 123 | #define LWIP_RAM_HEAP_POINTER lwip_ram_heap 124 | 125 | // Number of simultaneously queued TCP segments. 126 | #define MEMP_NUM_TCP_SEG MBED_CONF_LWIP_MEMP_NUM_TCP_SEG 127 | 128 | // TCP Maximum segment size. 129 | #define TCP_MSS MBED_CONF_LWIP_TCP_MSS 130 | 131 | // TCP sender buffer space (bytes). 132 | #define TCP_SND_BUF MBED_CONF_LWIP_TCP_SND_BUF 133 | 134 | // TCP sender buffer space (bytes). 135 | #define TCP_WND MBED_CONF_LWIP_TCP_WND 136 | 137 | #define TCP_MAXRTX MBED_CONF_LWIP_TCP_MAXRTX 138 | 139 | #define TCP_SYNMAXRTX MBED_CONF_LWIP_TCP_SYNMAXRTX 140 | 141 | // Number of pool pbufs. 142 | // Each requires 684 bytes of RAM (if MSS=536 and PBUF_POOL_BUFSIZE defaulting to be based on MSS) 143 | #define PBUF_POOL_SIZE MBED_CONF_LWIP_PBUF_POOL_SIZE 144 | 145 | #ifdef MBED_CONF_LWIP_PBUF_POOL_BUFSIZE 146 | #undef PBUF_POOL_BUFSIZE 147 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_LWIP_PBUF_POOL_BUFSIZE) 148 | #else 149 | #ifndef PBUF_POOL_BUFSIZE 150 | #if LWIP_IPV6 151 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 152 | #elif LWIP_IPV4 153 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+20+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 154 | #endif 155 | #endif 156 | #endif 157 | 158 | #define MEM_SIZE MBED_CONF_LWIP_MEM_SIZE 159 | 160 | // One tcp_pcb_listen is needed for each TCP server. 161 | // Each requires 72 bytes of RAM. 162 | #define MEMP_NUM_TCP_PCB_LISTEN MBED_CONF_LWIP_TCP_SERVER_MAX 163 | 164 | // One is tcp_pcb needed for each TCPSocket. 165 | // Each requires 196 bytes of RAM. 166 | #define MEMP_NUM_TCP_PCB MBED_CONF_LWIP_TCP_SOCKET_MAX 167 | 168 | // One udp_pcb is needed for each UDPSocket. 169 | // Each requires 84 bytes of RAM (total rounded to multiple of 512). 170 | #define MEMP_NUM_UDP_PCB MBED_CONF_LWIP_UDP_SOCKET_MAX 171 | 172 | // Number of non-pool pbufs. 173 | // Each requires 92 bytes of RAM. 174 | #define MEMP_NUM_PBUF MBED_CONF_LWIP_NUM_PBUF 175 | 176 | // Each netbuf requires 64 bytes of RAM. 177 | #define MEMP_NUM_NETBUF MBED_CONF_LWIP_NUM_NETBUF 178 | 179 | // One netconn is needed for each UDPSocket or TCPSocket. 180 | // Each requires 236 bytes of RAM (total rounded to multiple of 512). 181 | #define MEMP_NUM_NETCONN MBED_CONF_LWIP_SOCKET_MAX 182 | 183 | #if MBED_CONF_LWIP_TCP_ENABLED 184 | #define LWIP_TCP 1 185 | #define TCP_OVERSIZE 0 186 | #define LWIP_TCP_KEEPALIVE 1 187 | 188 | #define TCP_CLOSE_TIMEOUT MBED_CONF_LWIP_TCP_CLOSE_TIMEOUT 189 | 190 | #else 191 | #define LWIP_TCP 0 192 | #endif 193 | 194 | #define LWIP_DNS 1 195 | // Only DNS address storage is enabled 196 | #define LWIP_FULL_DNS 0 197 | #define LWIP_SOCKET 0 198 | 199 | #define SO_REUSE 1 200 | 201 | // Support Multicast 202 | #include "stdlib.h" 203 | #define LWIP_IGMP LWIP_IPV4 204 | #define LWIP_RAND() lwip_get_random() 205 | 206 | #define LWIP_COMPAT_SOCKETS 0 207 | #define LWIP_POSIX_SOCKETS_IO_NAMES 0 208 | 209 | #define LWIP_BROADCAST_PING 1 210 | 211 | // Fragmentation on, as per IPv4 default 212 | #define LWIP_IPV6_FRAG LWIP_IPV6 213 | 214 | // Queuing, default is "disabled", as per IPv4 default (so actually queues 1) 215 | #define LWIP_ND6_QUEUEING MBED_CONF_ND6_QUEUEING 216 | 217 | // Debug Options 218 | #define NETIF_DEBUG LWIP_DBG_OFF 219 | #define PBUF_DEBUG LWIP_DBG_OFF 220 | #define API_LIB_DEBUG LWIP_DBG_OFF 221 | #define API_MSG_DEBUG LWIP_DBG_OFF 222 | #define SOCKETS_DEBUG LWIP_DBG_OFF 223 | #define ICMP_DEBUG LWIP_DBG_OFF 224 | #define IGMP_DEBUG LWIP_DBG_OFF 225 | #define INET_DEBUG LWIP_DBG_OFF 226 | #define IP_DEBUG LWIP_DBG_OFF 227 | #define IP_REASS_DEBUG LWIP_DBG_OFF 228 | #define RAW_DEBUG LWIP_DBG_OFF 229 | #define MEM_DEBUG LWIP_DBG_OFF 230 | #define MEMP_DEBUG LWIP_DBG_OFF 231 | #define SYS_DEBUG LWIP_DBG_OFF 232 | #define TIMERS_DEBUG LWIP_DBG_OFF 233 | #define TCP_DEBUG LWIP_DBG_OFF 234 | #define TCP_INPUT_DEBUG LWIP_DBG_OFF 235 | #define TCP_FR_DEBUG LWIP_DBG_OFF 236 | #define TCP_RTO_DEBUG LWIP_DBG_OFF 237 | #define TCP_CWND_DEBUG LWIP_DBG_OFF 238 | #define TCP_WND_DEBUG LWIP_DBG_OFF 239 | #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 240 | #define TCP_RST_DEBUG LWIP_DBG_OFF 241 | #define TCP_QLEN_DEBUG LWIP_DBG_OFF 242 | #define UDP_DEBUG LWIP_DBG_OFF 243 | #define TCPIP_DEBUG LWIP_DBG_OFF 244 | #define SLIP_DEBUG LWIP_DBG_OFF 245 | #define DHCP_DEBUG LWIP_DBG_OFF 246 | #define AUTOIP_DEBUG LWIP_DBG_OFF 247 | #define DNS_DEBUG LWIP_DBG_OFF 248 | #define IP6_DEBUG LWIP_DBG_OFF 249 | 250 | #define ETHARP_DEBUG LWIP_DBG_OFF 251 | #define UDP_LPC_EMAC LWIP_DBG_OFF 252 | 253 | #ifdef LWIP_DEBUG 254 | #define MEMP_OVERFLOW_CHECK 1 255 | #define MEMP_SANITY_CHECK 1 256 | #define LWIP_DBG_TYPES_ON LWIP_DBG_ON 257 | #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL 258 | #else 259 | #define LWIP_NOASSERT 1 260 | #define LWIP_STATS 0 261 | #endif 262 | 263 | #define TRACE_TO_ASCII_HEX_DUMP 0 264 | 265 | #define LWIP_PLATFORM_BYTESWAP 1 266 | 267 | #define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 268 | 269 | // Interface type configuration 270 | 271 | #if MBED_CONF_LWIP_ETHERNET_ENABLED 272 | #define LWIP_ARP 1 273 | #define LWIP_ETHERNET 1 274 | #define LWIP_DHCP LWIP_IPV4 275 | #else 276 | #define LWIP_ARP 0 277 | #define LWIP_ETHERNET 0 278 | #endif // MBED_CONF_LWIP_ETHERNET_ENABLED 279 | 280 | #if MBED_CONF_LWIP_L3IP_ENABLED 281 | #define LWIP_L3IP 1 282 | #else 283 | #define LWIP_L3IP 0 284 | #endif 285 | 286 | //Maximum size of network interface name 287 | #define INTERFACE_NAME_MAX_SIZE NSAPI_INTERFACE_NAME_MAX_SIZE 288 | // Note generic macro name used rather than MBED_CONF_LWIP_PPP_ENABLED 289 | // to allow users like PPPCellularInterface to detect that nsapi_ppp.h is available. 290 | 291 | // Enable PPP for now either from lwIP PPP configuration (obsolete) or from PPP service configuration 292 | #if MBED_CONF_PPP_ENABLED || MBED_CONF_LWIP_PPP_ENABLED 293 | 294 | #define PPP_SUPPORT 1 295 | 296 | #if MBED_CONF_PPP_IPV4_ENABLED || MBED_CONF_LWIP_IPV4_ENABLED 297 | #define LWIP 0x11991199 298 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV4_ENABLED 299 | #error LWIP: IPv4 PPP enabled but not IPv4 300 | #endif 301 | #undef LWIP 302 | #define PPP_IPV4_SUPPORT 1 303 | #endif 304 | 305 | #if MBED_CONF_PPP_IPV6_ENABLED || MBED_CONF_LWIP_IPV6_ENABLED 306 | #define LWIP 0x11991199 307 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV6_ENABLED 308 | #error LWIP: IPv6 PPP enabled but not IPv6 309 | #endif 310 | #undef LWIP 311 | #define PPP_IPV6_SUPPORT 1 312 | // Later to be dynamic for use for multiple interfaces 313 | #define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 314 | #endif 315 | 316 | #endif 317 | 318 | #define LWIP_NETBUF_RECVINFO MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED 319 | 320 | // Make sure we default these to off, so 321 | // LWIP doesn't default to on 322 | #ifndef LWIP_ARP 323 | #define LWIP_ARP 0 324 | #endif 325 | 326 | // Checksum-on-copy disabled due to https://savannah.nongnu.org/bugs/?50914 327 | #define LWIP_CHECKSUM_ON_COPY 0 328 | 329 | #define LWIP_NETIF_HOSTNAME 1 330 | #define LWIP_NETIF_STATUS_CALLBACK 1 331 | #define LWIP_NETIF_LINK_CALLBACK 1 332 | 333 | #define DNS_TABLE_SIZE 2 334 | #define DNS_MAX_NAME_LENGTH 128 335 | 336 | #include "lwip_random.h" 337 | #include "lwip_tcp_isn.h" 338 | #define LWIP_HOOK_TCP_ISN lwip_hook_tcp_isn 339 | #ifdef MBEDTLS_MD5_C 340 | #define LWIP_USE_EXTERNAL_MBEDTLS 1 341 | #else 342 | #define LWIP_USE_EXTERNAL_MBEDTLS 0 343 | #endif 344 | 345 | #define LWIP_ND6_RDNSS_MAX_DNS_SERVERS MBED_CONF_LWIP_ND6_RDNSS_MAX_DNS_SERVERS 346 | 347 | #endif /* LWIPOPTS_H_ */ 348 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.5.2/libraries/SocketWrapper/src/MbedUdp.cpp: -------------------------------------------------------------------------------- 1 | #include "MbedUdp.h" 2 | 3 | arduino::MbedUDP::MbedUDP() { 4 | _packet_buffer = new uint8_t[WIFI_UDP_BUFFER_SIZE]; 5 | _current_packet = NULL; 6 | _current_packet_size = 0; 7 | // if this allocation fails then ::begin will fail 8 | } 9 | 10 | arduino::MbedUDP::~MbedUDP() { 11 | delete[] _packet_buffer; 12 | } 13 | 14 | uint8_t arduino::MbedUDP::begin(uint16_t port) { 15 | // success = 1, fail = 0 16 | 17 | nsapi_error_t rt = _socket.open(getNetwork()); 18 | if (rt != NSAPI_ERROR_OK) { 19 | return 0; 20 | } 21 | 22 | if (_socket.bind(port) < 0) { 23 | return 0; //Failed to bind UDP Socket to port 24 | } 25 | 26 | if (!_packet_buffer) { 27 | return 0; 28 | } 29 | 30 | _socket.set_blocking(false); 31 | _socket.set_timeout(0); 32 | 33 | return 1; 34 | } 35 | 36 | uint8_t arduino::MbedUDP::beginMulticast(IPAddress ip, uint16_t port) { 37 | // success = 1, fail = 0 38 | if (begin(port) != 1) { 39 | return 0; 40 | } 41 | 42 | SocketAddress socketAddress = SocketHelpers::socketAddressFromIpAddress(ip, port); 43 | 44 | if (_socket.join_multicast_group(socketAddress) != NSAPI_ERROR_OK) { 45 | printf("Error joining the multicast group\n"); 46 | return 0; 47 | } 48 | 49 | return 1; 50 | } 51 | 52 | void arduino::MbedUDP::stop() { 53 | _socket.close(); 54 | } 55 | 56 | int arduino::MbedUDP::beginPacket(IPAddress ip, uint16_t port) { 57 | _host = SocketHelpers::socketAddressFromIpAddress(ip, port); 58 | //If IP is null and port is 0 the initialization failed 59 | txBuffer.clear(); 60 | return (_host.get_ip_address() == nullptr && _host.get_port() == 0) ? 0 : 1; 61 | } 62 | 63 | int arduino::MbedUDP::beginPacket(const char *host, uint16_t port) { 64 | _host = SocketAddress(host, port); 65 | txBuffer.clear(); 66 | getNetwork()->gethostbyname(host, &_host); 67 | //If IP is null and port is 0 the initialization failed 68 | return (_host.get_ip_address() == nullptr && _host.get_port() == 0) ? 0 : 1; 69 | } 70 | 71 | int arduino::MbedUDP::endPacket() { 72 | _socket.set_blocking(true); 73 | _socket.set_timeout(1000); 74 | 75 | size_t size = txBuffer.available(); 76 | uint8_t buffer[size]; 77 | for (int i = 0; i < size; i++) { 78 | buffer[i] = txBuffer.read_char(); 79 | } 80 | 81 | nsapi_size_or_error_t ret = _socket.sendto(_host, buffer, size); 82 | _socket.set_blocking(false); 83 | _socket.set_timeout(0); 84 | if (ret < 0) { 85 | return 0; 86 | } 87 | return size; 88 | } 89 | 90 | // Write a single byte into the packet 91 | size_t arduino::MbedUDP::write(uint8_t byte) { 92 | return write(&byte, 1); 93 | } 94 | 95 | // Write size bytes from buffer into the packet 96 | size_t arduino::MbedUDP::write(const uint8_t *buffer, size_t size) { 97 | for (int i = 0; i _packet_buffer + _current_packet_size) { 146 | // try reading the next packet... 147 | if (parsePacket() > 0) { 148 | // if so, read first byte of next packet; 149 | return read(); 150 | } else { 151 | // no new data... not sure what to return here now 152 | return -1; 153 | } 154 | } 155 | 156 | return _current_packet[0]; 157 | } 158 | 159 | // Read up to len bytes from the current packet and place them into buffer 160 | // Returns the number of bytes read, or 0 if none are available 161 | int arduino::MbedUDP::read(unsigned char *buffer, size_t len) { 162 | // Q: does Arduino read() function handle fragmentation? I won't for now... 163 | if (_current_packet == NULL) { 164 | if (parsePacket() == 0) return 0; 165 | } 166 | 167 | // how much data do we have in the current packet? 168 | int offset = _current_packet - _packet_buffer; 169 | if (offset < 0) { 170 | return 0; 171 | } 172 | 173 | int max_bytes = _current_packet_size - offset; 174 | if (max_bytes < 0) { 175 | return 0; 176 | } 177 | 178 | // at the end of the packet? 179 | if (max_bytes == 0) { 180 | // try read next packet... 181 | if (parsePacket() > 0) { 182 | return read(buffer, len); 183 | } else { 184 | return 0; 185 | } 186 | } 187 | 188 | if (len > (size_t)max_bytes) len = max_bytes; 189 | 190 | // copy to target buffer 191 | memcpy(buffer, _current_packet, len); 192 | 193 | _current_packet += len; 194 | 195 | return len; 196 | } 197 | 198 | IPAddress arduino::MbedUDP::remoteIP() { 199 | nsapi_addr_t address = _remoteHost.get_addr(); 200 | return IPAddress(address.bytes[0], address.bytes[1], address.bytes[2], address.bytes[3]); 201 | } 202 | 203 | uint16_t arduino::MbedUDP::remotePort() { 204 | return _remoteHost.get_port(); 205 | } 206 | 207 | void arduino::MbedUDP::flush() { 208 | // TODO: a real check to ensure transmission has been completed 209 | } 210 | 211 | int arduino::MbedUDP::peek() { 212 | if (_current_packet_size < 1) { 213 | return -1; 214 | } 215 | 216 | return _current_packet[0]; 217 | } 218 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.5.2/libraries/SocketWrapper/src/MbedUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | MbedUdp.h - UDP implementation using mbed Sockets 3 | Copyright (c) 2021 Arduino SA. All right reserved. 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | This library is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | Lesser General Public License for more details. 12 | You should have received a copy of the GNU Lesser General Public 13 | License along with this library; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 15 | */ 16 | 17 | #ifndef MBEDUDP_H 18 | #define MBEDUDP_H 19 | 20 | #include "Arduino.h" 21 | #include "SocketHelpers.h" 22 | #include "api/Udp.h" 23 | 24 | #include "netsocket/SocketAddress.h" 25 | #include "netsocket/UDPSocket.h" 26 | 27 | #ifndef WIFI_UDP_BUFFER_SIZE 28 | #define WIFI_UDP_BUFFER_SIZE 508 29 | #endif 30 | 31 | namespace arduino { 32 | 33 | class MbedUDP : public UDP { 34 | private: 35 | UDPSocket _socket; // Mbed OS socket 36 | SocketAddress _host; // Host to be used to send data 37 | SocketAddress _remoteHost; // Remote host that sent incoming packets 38 | 39 | uint8_t* _packet_buffer; // Raw packet buffer (contains data we got from the UDPSocket) 40 | 41 | // The Arduino APIs allow you to iterate through this buffer, so we need to be able to iterate over the current packet 42 | // these two variables are used to cache the state of the current packet 43 | uint8_t* _current_packet; 44 | size_t _current_packet_size; 45 | 46 | RingBufferN txBuffer; 47 | 48 | protected: 49 | virtual NetworkInterface* getNetwork() = 0; 50 | 51 | public: 52 | MbedUDP(); // Constructor 53 | ~MbedUDP(); 54 | virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 55 | virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 if there are no sockets available to use 56 | virtual void stop(); // Finish with the UDP socket 57 | 58 | // Sending UDP packets 59 | 60 | // Start building up a packet to send to the remote host specific in ip and port 61 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 62 | virtual int beginPacket(IPAddress ip, uint16_t port); 63 | // Start building up a packet to send to the remote host specific in host and port 64 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 65 | virtual int beginPacket(const char* host, uint16_t port); 66 | // Finish off this packet and send it 67 | // Returns 1 if the packet was sent successfully, 0 if there was an error 68 | virtual int endPacket(); 69 | // Write a single byte into the packet 70 | virtual size_t write(uint8_t); 71 | // Write size bytes from buffer into the packet 72 | virtual size_t write(const uint8_t* buffer, size_t size); 73 | 74 | using Print::write; 75 | 76 | // Start processing the next available incoming packet 77 | // Returns the size of the packet in bytes, or 0 if no packets are available 78 | virtual int parsePacket(); 79 | // Number of bytes remaining in the current packet 80 | virtual int available(); 81 | // Read a single byte from the current packet 82 | virtual int read(); 83 | // Read up to len bytes from the current packet and place them into buffer 84 | // Returns the number of bytes read, or 0 if none are available 85 | virtual int read(unsigned char* buffer, size_t len); 86 | // Read up to len characters from the current packet and place them into buffer 87 | // Returns the number of characters read, or 0 if none are available 88 | virtual int read(char* buffer, size_t len) { 89 | return read((unsigned char*)buffer, len); 90 | }; 91 | // Return the next byte from the current packet without moving on to the next byte 92 | virtual int peek(); 93 | virtual void flush(); // Finish reading the current packet 94 | 95 | // Return the IP address of the host who sent the current incoming packet 96 | virtual IPAddress remoteIP(); 97 | // // Return the port of the host who sent the current incoming packet 98 | virtual uint16_t remotePort(); 99 | 100 | friend class MbedSocketClass; 101 | }; 102 | 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.5.2/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.6.1/cores/arduino/mbed/connectivity/lwipstack/include/lwipstack/lwipopts.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012 mbed.org, MIT License 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 7 | * furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or 10 | * substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | #ifndef LWIPOPTS_H 20 | #define LWIPOPTS_H 21 | 22 | // Workaround for Linux timeval 23 | #if defined (TOOLCHAIN_GCC) 24 | #define LWIP_TIMEVAL_PRIVATE 0 25 | #include 26 | #endif 27 | #include "nsapi_types.h" 28 | #include "mbed_retarget.h" 29 | 30 | // KH fix 31 | #include 32 | ///////////////////////// 33 | 34 | // Operating System 35 | #define NO_SYS 0 36 | 37 | #if !MBED_CONF_LWIP_IPV4_ENABLED && !MBED_CONF_LWIP_IPV6_ENABLED 38 | #error "Either IPv4 or IPv6 must be enabled." 39 | #endif 40 | 41 | #define LWIP_IPV4 MBED_CONF_LWIP_IPV4_ENABLED 42 | 43 | #define LWIP_IPV6 MBED_CONF_LWIP_IPV6_ENABLED 44 | 45 | #define LWIP_PROVIDE_ERRNO 0 46 | 47 | // On dual stack configuration how long to wait for both or preferred stack 48 | // addresses before completing bring up. 49 | #if LWIP_IPV4 && LWIP_IPV6 50 | #if MBED_CONF_LWIP_ADDR_TIMEOUT_MODE 51 | #define BOTH_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 52 | #define PREF_ADDR_TIMEOUT 0 53 | #else 54 | #define PREF_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 55 | #define BOTH_ADDR_TIMEOUT 0 56 | #endif 57 | #else 58 | #define PREF_ADDR_TIMEOUT 0 59 | #define BOTH_ADDR_TIMEOUT 0 60 | #endif 61 | 62 | 63 | #define DHCP_TIMEOUT MBED_CONF_LWIP_DHCP_TIMEOUT 64 | 65 | #define LINK_TIMEOUT 60 66 | 67 | #define PREF_IPV4 1 68 | #define PREF_IPV6 2 69 | 70 | #if MBED_CONF_LWIP_IP_VER_PREF == 6 71 | #define IP_VERSION_PREF PREF_IPV6 72 | #elif MBED_CONF_LWIP_IP_VER_PREF == 4 73 | #define IP_VERSION_PREF PREF_IPV4 74 | #else 75 | #error "Either IPv4 or IPv6 must be preferred." 76 | #endif 77 | 78 | #undef LWIP_DEBUG 79 | #if MBED_CONF_LWIP_DEBUG_ENABLED 80 | #define LWIP_DEBUG 1 81 | #endif 82 | 83 | #if NO_SYS == 0 84 | #include "cmsis_os2.h" 85 | 86 | #define SYS_LIGHTWEIGHT_PROT 1 87 | 88 | #define LWIP_RAW MBED_CONF_LWIP_RAW_SOCKET_ENABLED 89 | 90 | #define MEMP_NUM_TCPIP_MSG_INPKT MBED_CONF_LWIP_MEMP_NUM_TCPIP_MSG_INPKT 91 | 92 | // Thread stacks use 8-byte alignment 93 | #define LWIP_ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) 94 | 95 | #ifdef LWIP_DEBUG 96 | // For LWIP debug, double the stack 97 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE*2, 8) 98 | #elif MBED_DEBUG 99 | // When debug is enabled on the build increase stack 25 percent 100 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE + MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE / 4, 8) 101 | #else 102 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE, 8) 103 | #endif 104 | 105 | // Thread priority (osPriorityNormal by default) 106 | #define TCPIP_THREAD_PRIO (MBED_CONF_LWIP_TCPIP_THREAD_PRIORITY) 107 | 108 | #ifdef LWIP_DEBUG 109 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE*2, 8) 110 | #else 111 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE, 8) 112 | #endif 113 | 114 | #define MEMP_NUM_SYS_TIMEOUT 16 115 | 116 | #define sys_msleep(ms) sys_msleep(ms) 117 | 118 | #endif 119 | 120 | // 32-bit alignment 121 | #define MEM_ALIGNMENT 4 122 | 123 | #define LWIP_RAM_HEAP_POINTER lwip_ram_heap 124 | 125 | // Number of simultaneously queued TCP segments. 126 | #define MEMP_NUM_TCP_SEG MBED_CONF_LWIP_MEMP_NUM_TCP_SEG 127 | 128 | // TCP Maximum segment size. 129 | #define TCP_MSS MBED_CONF_LWIP_TCP_MSS 130 | 131 | // TCP sender buffer space (bytes). 132 | #define TCP_SND_BUF MBED_CONF_LWIP_TCP_SND_BUF 133 | 134 | // TCP sender buffer space (bytes). 135 | #define TCP_WND MBED_CONF_LWIP_TCP_WND 136 | 137 | #define TCP_MAXRTX MBED_CONF_LWIP_TCP_MAXRTX 138 | 139 | #define TCP_SYNMAXRTX MBED_CONF_LWIP_TCP_SYNMAXRTX 140 | 141 | // Number of pool pbufs. 142 | // Each requires 684 bytes of RAM (if MSS=536 and PBUF_POOL_BUFSIZE defaulting to be based on MSS) 143 | #define PBUF_POOL_SIZE MBED_CONF_LWIP_PBUF_POOL_SIZE 144 | 145 | #ifdef MBED_CONF_LWIP_PBUF_POOL_BUFSIZE 146 | #undef PBUF_POOL_BUFSIZE 147 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_LWIP_PBUF_POOL_BUFSIZE) 148 | #else 149 | #ifndef PBUF_POOL_BUFSIZE 150 | #if LWIP_IPV6 151 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 152 | #elif LWIP_IPV4 153 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+20+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 154 | #endif 155 | #endif 156 | #endif 157 | 158 | #define MEM_SIZE MBED_CONF_LWIP_MEM_SIZE 159 | 160 | // One tcp_pcb_listen is needed for each TCP server. 161 | // Each requires 72 bytes of RAM. 162 | #define MEMP_NUM_TCP_PCB_LISTEN MBED_CONF_LWIP_TCP_SERVER_MAX 163 | 164 | // One is tcp_pcb needed for each TCPSocket. 165 | // Each requires 196 bytes of RAM. 166 | #define MEMP_NUM_TCP_PCB MBED_CONF_LWIP_TCP_SOCKET_MAX 167 | 168 | // One udp_pcb is needed for each UDPSocket. 169 | // Each requires 84 bytes of RAM (total rounded to multiple of 512). 170 | #define MEMP_NUM_UDP_PCB MBED_CONF_LWIP_UDP_SOCKET_MAX 171 | 172 | // Number of non-pool pbufs. 173 | // Each requires 92 bytes of RAM. 174 | #define MEMP_NUM_PBUF MBED_CONF_LWIP_NUM_PBUF 175 | 176 | // Each netbuf requires 64 bytes of RAM. 177 | #define MEMP_NUM_NETBUF MBED_CONF_LWIP_NUM_NETBUF 178 | 179 | // One netconn is needed for each UDPSocket or TCPSocket. 180 | // Each requires 236 bytes of RAM (total rounded to multiple of 512). 181 | #define MEMP_NUM_NETCONN MBED_CONF_LWIP_SOCKET_MAX 182 | 183 | #if MBED_CONF_LWIP_TCP_ENABLED 184 | #define LWIP_TCP 1 185 | #define TCP_OVERSIZE 0 186 | #define LWIP_TCP_KEEPALIVE 1 187 | 188 | #define TCP_CLOSE_TIMEOUT MBED_CONF_LWIP_TCP_CLOSE_TIMEOUT 189 | 190 | #else 191 | #define LWIP_TCP 0 192 | #endif 193 | 194 | #define LWIP_DNS 1 195 | // Only DNS address storage is enabled 196 | #define LWIP_FULL_DNS 0 197 | #define LWIP_SOCKET 0 198 | 199 | #define SO_REUSE 1 200 | 201 | // Support Multicast 202 | #include "stdlib.h" 203 | #define LWIP_IGMP LWIP_IPV4 204 | #define LWIP_RAND() lwip_get_random() 205 | 206 | #define LWIP_COMPAT_SOCKETS 0 207 | #define LWIP_POSIX_SOCKETS_IO_NAMES 0 208 | 209 | #define LWIP_BROADCAST_PING 1 210 | 211 | // Fragmentation on, as per IPv4 default 212 | #define LWIP_IPV6_FRAG LWIP_IPV6 213 | 214 | // Queuing, default is "disabled", as per IPv4 default (so actually queues 1) 215 | #define LWIP_ND6_QUEUEING MBED_CONF_ND6_QUEUEING 216 | 217 | // Debug Options 218 | #define NETIF_DEBUG LWIP_DBG_OFF 219 | #define PBUF_DEBUG LWIP_DBG_OFF 220 | #define API_LIB_DEBUG LWIP_DBG_OFF 221 | #define API_MSG_DEBUG LWIP_DBG_OFF 222 | #define SOCKETS_DEBUG LWIP_DBG_OFF 223 | #define ICMP_DEBUG LWIP_DBG_OFF 224 | #define IGMP_DEBUG LWIP_DBG_OFF 225 | #define INET_DEBUG LWIP_DBG_OFF 226 | #define IP_DEBUG LWIP_DBG_OFF 227 | #define IP_REASS_DEBUG LWIP_DBG_OFF 228 | #define RAW_DEBUG LWIP_DBG_OFF 229 | #define MEM_DEBUG LWIP_DBG_OFF 230 | #define MEMP_DEBUG LWIP_DBG_OFF 231 | #define SYS_DEBUG LWIP_DBG_OFF 232 | #define TIMERS_DEBUG LWIP_DBG_OFF 233 | #define TCP_DEBUG LWIP_DBG_OFF 234 | #define TCP_INPUT_DEBUG LWIP_DBG_OFF 235 | #define TCP_FR_DEBUG LWIP_DBG_OFF 236 | #define TCP_RTO_DEBUG LWIP_DBG_OFF 237 | #define TCP_CWND_DEBUG LWIP_DBG_OFF 238 | #define TCP_WND_DEBUG LWIP_DBG_OFF 239 | #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 240 | #define TCP_RST_DEBUG LWIP_DBG_OFF 241 | #define TCP_QLEN_DEBUG LWIP_DBG_OFF 242 | #define UDP_DEBUG LWIP_DBG_OFF 243 | #define TCPIP_DEBUG LWIP_DBG_OFF 244 | #define SLIP_DEBUG LWIP_DBG_OFF 245 | #define DHCP_DEBUG LWIP_DBG_OFF 246 | #define AUTOIP_DEBUG LWIP_DBG_OFF 247 | #define DNS_DEBUG LWIP_DBG_OFF 248 | #define IP6_DEBUG LWIP_DBG_OFF 249 | 250 | #define ETHARP_DEBUG LWIP_DBG_OFF 251 | #define UDP_LPC_EMAC LWIP_DBG_OFF 252 | 253 | #ifdef LWIP_DEBUG 254 | #define MEMP_OVERFLOW_CHECK 1 255 | #define MEMP_SANITY_CHECK 1 256 | #define LWIP_DBG_TYPES_ON LWIP_DBG_ON 257 | #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL 258 | #else 259 | #define LWIP_NOASSERT 1 260 | #define LWIP_STATS 0 261 | #endif 262 | 263 | #define TRACE_TO_ASCII_HEX_DUMP 0 264 | 265 | #define LWIP_PLATFORM_BYTESWAP 1 266 | 267 | #define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 268 | 269 | // Interface type configuration 270 | 271 | #if MBED_CONF_LWIP_ETHERNET_ENABLED 272 | #define LWIP_ARP 1 273 | #define LWIP_ETHERNET 1 274 | #define LWIP_DHCP LWIP_IPV4 275 | #else 276 | #define LWIP_ARP 0 277 | #define LWIP_ETHERNET 0 278 | #endif // MBED_CONF_LWIP_ETHERNET_ENABLED 279 | 280 | #if MBED_CONF_LWIP_L3IP_ENABLED 281 | #define LWIP_L3IP 1 282 | #else 283 | #define LWIP_L3IP 0 284 | #endif 285 | 286 | //Maximum size of network interface name 287 | #define INTERFACE_NAME_MAX_SIZE NSAPI_INTERFACE_NAME_MAX_SIZE 288 | // Note generic macro name used rather than MBED_CONF_LWIP_PPP_ENABLED 289 | // to allow users like PPPCellularInterface to detect that nsapi_ppp.h is available. 290 | 291 | // Enable PPP for now either from lwIP PPP configuration (obsolete) or from PPP service configuration 292 | #if MBED_CONF_PPP_ENABLED || MBED_CONF_LWIP_PPP_ENABLED 293 | 294 | #define PPP_SUPPORT 1 295 | 296 | #if MBED_CONF_PPP_IPV4_ENABLED || MBED_CONF_LWIP_IPV4_ENABLED 297 | #define LWIP 0x11991199 298 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV4_ENABLED 299 | #error LWIP: IPv4 PPP enabled but not IPv4 300 | #endif 301 | #undef LWIP 302 | #define PPP_IPV4_SUPPORT 1 303 | #endif 304 | 305 | #if MBED_CONF_PPP_IPV6_ENABLED || MBED_CONF_LWIP_IPV6_ENABLED 306 | #define LWIP 0x11991199 307 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV6_ENABLED 308 | #error LWIP: IPv6 PPP enabled but not IPv6 309 | #endif 310 | #undef LWIP 311 | #define PPP_IPV6_SUPPORT 1 312 | // Later to be dynamic for use for multiple interfaces 313 | #define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 314 | #endif 315 | 316 | #endif 317 | 318 | #define LWIP_NETBUF_RECVINFO MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED 319 | 320 | // Make sure we default these to off, so 321 | // LWIP doesn't default to on 322 | #ifndef LWIP_ARP 323 | #define LWIP_ARP 0 324 | #endif 325 | 326 | // Checksum-on-copy disabled due to https://savannah.nongnu.org/bugs/?50914 327 | #define LWIP_CHECKSUM_ON_COPY 0 328 | 329 | #define LWIP_NETIF_HOSTNAME 1 330 | #define LWIP_NETIF_STATUS_CALLBACK 1 331 | #define LWIP_NETIF_LINK_CALLBACK 1 332 | 333 | #define DNS_TABLE_SIZE 2 334 | #define DNS_MAX_NAME_LENGTH 128 335 | 336 | #include "lwip_random.h" 337 | #include "lwip_tcp_isn.h" 338 | #define LWIP_HOOK_TCP_ISN lwip_hook_tcp_isn 339 | #ifdef MBEDTLS_MD5_C 340 | #define LWIP_USE_EXTERNAL_MBEDTLS 1 341 | #else 342 | #define LWIP_USE_EXTERNAL_MBEDTLS 0 343 | #endif 344 | 345 | #define LWIP_ND6_RDNSS_MAX_DNS_SERVERS MBED_CONF_LWIP_ND6_RDNSS_MAX_DNS_SERVERS 346 | 347 | #endif /* LWIPOPTS_H_ */ 348 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.6.1/libraries/SocketWrapper/src/MbedUdp.cpp: -------------------------------------------------------------------------------- 1 | #include "MbedUdp.h" 2 | 3 | arduino::MbedUDP::MbedUDP() { 4 | _packet_buffer = new uint8_t[WIFI_UDP_BUFFER_SIZE]; 5 | _current_packet = NULL; 6 | _current_packet_size = 0; 7 | // if this allocation fails then ::begin will fail 8 | } 9 | 10 | arduino::MbedUDP::~MbedUDP() { 11 | delete[] _packet_buffer; 12 | } 13 | 14 | uint8_t arduino::MbedUDP::begin(uint16_t port) { 15 | // success = 1, fail = 0 16 | 17 | nsapi_error_t rt = _socket.open(getNetwork()); 18 | if (rt != NSAPI_ERROR_OK) { 19 | return 0; 20 | } 21 | 22 | if (_socket.bind(port) < 0) { 23 | return 0; //Failed to bind UDP Socket to port 24 | } 25 | 26 | if (!_packet_buffer) { 27 | return 0; 28 | } 29 | 30 | _socket.set_blocking(false); 31 | _socket.set_timeout(0); 32 | 33 | return 1; 34 | } 35 | 36 | uint8_t arduino::MbedUDP::beginMulticast(IPAddress ip, uint16_t port) { 37 | // success = 1, fail = 0 38 | if (begin(port) != 1) { 39 | return 0; 40 | } 41 | 42 | SocketAddress socketAddress = SocketHelpers::socketAddressFromIpAddress(ip, port); 43 | 44 | if (_socket.join_multicast_group(socketAddress) != NSAPI_ERROR_OK) { 45 | printf("Error joining the multicast group\n"); 46 | return 0; 47 | } 48 | 49 | return 1; 50 | } 51 | 52 | void arduino::MbedUDP::stop() { 53 | _socket.close(); 54 | } 55 | 56 | int arduino::MbedUDP::beginPacket(IPAddress ip, uint16_t port) { 57 | _host = SocketHelpers::socketAddressFromIpAddress(ip, port); 58 | //If IP is null and port is 0 the initialization failed 59 | txBuffer.clear(); 60 | return (_host.get_ip_address() == nullptr && _host.get_port() == 0) ? 0 : 1; 61 | } 62 | 63 | int arduino::MbedUDP::beginPacket(const char *host, uint16_t port) { 64 | _host = SocketAddress(host, port); 65 | txBuffer.clear(); 66 | getNetwork()->gethostbyname(host, &_host); 67 | //If IP is null and port is 0 the initialization failed 68 | return (_host.get_ip_address() == nullptr && _host.get_port() == 0) ? 0 : 1; 69 | } 70 | 71 | int arduino::MbedUDP::endPacket() { 72 | _socket.set_blocking(true); 73 | _socket.set_timeout(1000); 74 | 75 | size_t size = txBuffer.available(); 76 | uint8_t buffer[size]; 77 | for (int i = 0; i < size; i++) { 78 | buffer[i] = txBuffer.read_char(); 79 | } 80 | 81 | nsapi_size_or_error_t ret = _socket.sendto(_host, buffer, size); 82 | _socket.set_blocking(false); 83 | _socket.set_timeout(0); 84 | if (ret < 0) { 85 | return 0; 86 | } 87 | return size; 88 | } 89 | 90 | // Write a single byte into the packet 91 | size_t arduino::MbedUDP::write(uint8_t byte) { 92 | return write(&byte, 1); 93 | } 94 | 95 | // Write size bytes from buffer into the packet 96 | size_t arduino::MbedUDP::write(const uint8_t *buffer, size_t size) { 97 | for (int i = 0; i _packet_buffer + _current_packet_size) { 146 | // try reading the next packet... 147 | if (parsePacket() > 0) { 148 | // if so, read first byte of next packet; 149 | return read(); 150 | } else { 151 | // no new data... not sure what to return here now 152 | return -1; 153 | } 154 | } 155 | 156 | return _current_packet[0]; 157 | } 158 | 159 | // Read up to len bytes from the current packet and place them into buffer 160 | // Returns the number of bytes read, or 0 if none are available 161 | int arduino::MbedUDP::read(unsigned char *buffer, size_t len) { 162 | // Q: does Arduino read() function handle fragmentation? I won't for now... 163 | if (_current_packet == NULL) { 164 | if (parsePacket() == 0) return 0; 165 | } 166 | 167 | // how much data do we have in the current packet? 168 | int offset = _current_packet - _packet_buffer; 169 | if (offset < 0) { 170 | return 0; 171 | } 172 | 173 | int max_bytes = _current_packet_size - offset; 174 | if (max_bytes < 0) { 175 | return 0; 176 | } 177 | 178 | // at the end of the packet? 179 | if (max_bytes == 0) { 180 | // try read next packet... 181 | if (parsePacket() > 0) { 182 | return read(buffer, len); 183 | } else { 184 | return 0; 185 | } 186 | } 187 | 188 | if (len > (size_t)max_bytes) len = max_bytes; 189 | 190 | // copy to target buffer 191 | memcpy(buffer, _current_packet, len); 192 | 193 | _current_packet += len; 194 | 195 | return len; 196 | } 197 | 198 | IPAddress arduino::MbedUDP::remoteIP() { 199 | nsapi_addr_t address = _remoteHost.get_addr(); 200 | return IPAddress(address.bytes[0], address.bytes[1], address.bytes[2], address.bytes[3]); 201 | } 202 | 203 | uint16_t arduino::MbedUDP::remotePort() { 204 | return _remoteHost.get_port(); 205 | } 206 | 207 | void arduino::MbedUDP::flush() { 208 | // TODO: a real check to ensure transmission has been completed 209 | } 210 | 211 | int arduino::MbedUDP::peek() { 212 | if (_current_packet_size < 1) { 213 | return -1; 214 | } 215 | 216 | return _current_packet[0]; 217 | } 218 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.6.1/libraries/SocketWrapper/src/MbedUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | MbedUdp.h - UDP implementation using mbed Sockets 3 | Copyright (c) 2021 Arduino SA. All right reserved. 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | This library is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | Lesser General Public License for more details. 12 | You should have received a copy of the GNU Lesser General Public 13 | License along with this library; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 15 | */ 16 | 17 | #ifndef MBEDUDP_H 18 | #define MBEDUDP_H 19 | 20 | #include "Arduino.h" 21 | #include "SocketHelpers.h" 22 | #include "api/Udp.h" 23 | 24 | #include "netsocket/SocketAddress.h" 25 | #include "netsocket/UDPSocket.h" 26 | 27 | #ifndef WIFI_UDP_BUFFER_SIZE 28 | #define WIFI_UDP_BUFFER_SIZE 508 29 | #endif 30 | 31 | namespace arduino { 32 | 33 | class MbedUDP : public UDP { 34 | private: 35 | UDPSocket _socket; // Mbed OS socket 36 | SocketAddress _host; // Host to be used to send data 37 | SocketAddress _remoteHost; // Remote host that sent incoming packets 38 | 39 | uint8_t* _packet_buffer; // Raw packet buffer (contains data we got from the UDPSocket) 40 | 41 | // The Arduino APIs allow you to iterate through this buffer, so we need to be able to iterate over the current packet 42 | // these two variables are used to cache the state of the current packet 43 | uint8_t* _current_packet; 44 | size_t _current_packet_size; 45 | 46 | RingBufferN txBuffer; 47 | 48 | protected: 49 | virtual NetworkInterface* getNetwork() = 0; 50 | 51 | public: 52 | MbedUDP(); // Constructor 53 | ~MbedUDP(); 54 | virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 55 | virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 if there are no sockets available to use 56 | virtual void stop(); // Finish with the UDP socket 57 | 58 | // Sending UDP packets 59 | 60 | // Start building up a packet to send to the remote host specific in ip and port 61 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 62 | virtual int beginPacket(IPAddress ip, uint16_t port); 63 | // Start building up a packet to send to the remote host specific in host and port 64 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 65 | virtual int beginPacket(const char* host, uint16_t port); 66 | // Finish off this packet and send it 67 | // Returns 1 if the packet was sent successfully, 0 if there was an error 68 | virtual int endPacket(); 69 | // Write a single byte into the packet 70 | virtual size_t write(uint8_t); 71 | // Write size bytes from buffer into the packet 72 | virtual size_t write(const uint8_t* buffer, size_t size); 73 | 74 | using Print::write; 75 | 76 | // Start processing the next available incoming packet 77 | // Returns the size of the packet in bytes, or 0 if no packets are available 78 | virtual int parsePacket(); 79 | // Number of bytes remaining in the current packet 80 | virtual int available(); 81 | // Read a single byte from the current packet 82 | virtual int read(); 83 | // Read up to len bytes from the current packet and place them into buffer 84 | // Returns the number of bytes read, or 0 if none are available 85 | virtual int read(unsigned char* buffer, size_t len); 86 | // Read up to len characters from the current packet and place them into buffer 87 | // Returns the number of characters read, or 0 if none are available 88 | virtual int read(char* buffer, size_t len) { 89 | return read((unsigned char*)buffer, len); 90 | }; 91 | // Return the next byte from the current packet without moving on to the next byte 92 | virtual int peek(); 93 | virtual void flush(); // Finish reading the current packet 94 | 95 | // Return the IP address of the host who sent the current incoming packet 96 | virtual IPAddress remoteIP(); 97 | // // Return the port of the host who sent the current incoming packet 98 | virtual uint16_t remotePort(); 99 | 100 | friend class MbedSocketClass; 101 | }; 102 | 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.6.1/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.7.2/cores/arduino/mbed/connectivity/lwipstack/include/lwipstack/lwipopts.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012 mbed.org, MIT License 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 7 | * furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or 10 | * substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | 19 | #ifndef LWIPOPTS_H 20 | #define LWIPOPTS_H 21 | 22 | // Workaround for Linux timeval 23 | #if defined (TOOLCHAIN_GCC) 24 | #define LWIP_TIMEVAL_PRIVATE 0 25 | #include 26 | #endif 27 | #include "nsapi_types.h" 28 | #include "mbed_retarget.h" 29 | 30 | // KH fix 31 | #include 32 | ///////////////////////// 33 | 34 | // Operating System 35 | #define NO_SYS 0 36 | 37 | #if !MBED_CONF_LWIP_IPV4_ENABLED && !MBED_CONF_LWIP_IPV6_ENABLED 38 | #error "Either IPv4 or IPv6 must be enabled." 39 | #endif 40 | 41 | #define LWIP_IPV4 MBED_CONF_LWIP_IPV4_ENABLED 42 | 43 | #define LWIP_IPV6 MBED_CONF_LWIP_IPV6_ENABLED 44 | 45 | #define LWIP_PROVIDE_ERRNO 0 46 | 47 | // On dual stack configuration how long to wait for both or preferred stack 48 | // addresses before completing bring up. 49 | #if LWIP_IPV4 && LWIP_IPV6 50 | #if MBED_CONF_LWIP_ADDR_TIMEOUT_MODE 51 | #define BOTH_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 52 | #define PREF_ADDR_TIMEOUT 0 53 | #else 54 | #define PREF_ADDR_TIMEOUT MBED_CONF_LWIP_ADDR_TIMEOUT 55 | #define BOTH_ADDR_TIMEOUT 0 56 | #endif 57 | #else 58 | #define PREF_ADDR_TIMEOUT 0 59 | #define BOTH_ADDR_TIMEOUT 0 60 | #endif 61 | 62 | 63 | #define DHCP_TIMEOUT MBED_CONF_LWIP_DHCP_TIMEOUT 64 | 65 | #define LINK_TIMEOUT 60 66 | 67 | #define PREF_IPV4 1 68 | #define PREF_IPV6 2 69 | 70 | #if MBED_CONF_LWIP_IP_VER_PREF == 6 71 | #define IP_VERSION_PREF PREF_IPV6 72 | #elif MBED_CONF_LWIP_IP_VER_PREF == 4 73 | #define IP_VERSION_PREF PREF_IPV4 74 | #else 75 | #error "Either IPv4 or IPv6 must be preferred." 76 | #endif 77 | 78 | #undef LWIP_DEBUG 79 | #if MBED_CONF_LWIP_DEBUG_ENABLED 80 | #define LWIP_DEBUG 1 81 | #endif 82 | 83 | #if NO_SYS == 0 84 | #include "cmsis_os2.h" 85 | 86 | #define SYS_LIGHTWEIGHT_PROT 1 87 | 88 | #define LWIP_RAW MBED_CONF_LWIP_RAW_SOCKET_ENABLED 89 | 90 | #define MEMP_NUM_TCPIP_MSG_INPKT MBED_CONF_LWIP_MEMP_NUM_TCPIP_MSG_INPKT 91 | 92 | // Thread stacks use 8-byte alignment 93 | #define LWIP_ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) 94 | 95 | #ifdef LWIP_DEBUG 96 | // For LWIP debug, double the stack 97 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE*2, 8) 98 | #elif MBED_DEBUG 99 | // When debug is enabled on the build increase stack 25 percent 100 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE + MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE / 4, 8) 101 | #else 102 | #define TCPIP_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE, 8) 103 | #endif 104 | 105 | // Thread priority (osPriorityNormal by default) 106 | #define TCPIP_THREAD_PRIO (MBED_CONF_LWIP_TCPIP_THREAD_PRIORITY) 107 | 108 | #ifdef LWIP_DEBUG 109 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE*2, 8) 110 | #else 111 | #define DEFAULT_THREAD_STACKSIZE LWIP_ALIGN_UP(MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE, 8) 112 | #endif 113 | 114 | #define MEMP_NUM_SYS_TIMEOUT 16 115 | 116 | #define sys_msleep(ms) sys_msleep(ms) 117 | 118 | #endif 119 | 120 | // 32-bit alignment 121 | #define MEM_ALIGNMENT 4 122 | 123 | #define LWIP_RAM_HEAP_POINTER lwip_ram_heap 124 | 125 | // Number of simultaneously queued TCP segments. 126 | #define MEMP_NUM_TCP_SEG MBED_CONF_LWIP_MEMP_NUM_TCP_SEG 127 | 128 | // TCP Maximum segment size. 129 | #define TCP_MSS MBED_CONF_LWIP_TCP_MSS 130 | 131 | // TCP sender buffer space (bytes). 132 | #define TCP_SND_BUF MBED_CONF_LWIP_TCP_SND_BUF 133 | 134 | // TCP sender buffer space (bytes). 135 | #define TCP_WND MBED_CONF_LWIP_TCP_WND 136 | 137 | #define TCP_MAXRTX MBED_CONF_LWIP_TCP_MAXRTX 138 | 139 | #define TCP_SYNMAXRTX MBED_CONF_LWIP_TCP_SYNMAXRTX 140 | 141 | // Number of pool pbufs. 142 | // Each requires 684 bytes of RAM (if MSS=536 and PBUF_POOL_BUFSIZE defaulting to be based on MSS) 143 | #define PBUF_POOL_SIZE MBED_CONF_LWIP_PBUF_POOL_SIZE 144 | 145 | #ifdef MBED_CONF_LWIP_PBUF_POOL_BUFSIZE 146 | #undef PBUF_POOL_BUFSIZE 147 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_LWIP_PBUF_POOL_BUFSIZE) 148 | #else 149 | #ifndef PBUF_POOL_BUFSIZE 150 | #if LWIP_IPV6 151 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 152 | #elif LWIP_IPV4 153 | #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+20+20+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) 154 | #endif 155 | #endif 156 | #endif 157 | 158 | #define MEM_SIZE MBED_CONF_LWIP_MEM_SIZE 159 | 160 | // One tcp_pcb_listen is needed for each TCP server. 161 | // Each requires 72 bytes of RAM. 162 | #define MEMP_NUM_TCP_PCB_LISTEN MBED_CONF_LWIP_TCP_SERVER_MAX 163 | 164 | // One is tcp_pcb needed for each TCPSocket. 165 | // Each requires 196 bytes of RAM. 166 | #define MEMP_NUM_TCP_PCB MBED_CONF_LWIP_TCP_SOCKET_MAX 167 | 168 | // One udp_pcb is needed for each UDPSocket. 169 | // Each requires 84 bytes of RAM (total rounded to multiple of 512). 170 | #define MEMP_NUM_UDP_PCB MBED_CONF_LWIP_UDP_SOCKET_MAX 171 | 172 | // Number of non-pool pbufs. 173 | // Each requires 92 bytes of RAM. 174 | #define MEMP_NUM_PBUF MBED_CONF_LWIP_NUM_PBUF 175 | 176 | // Each netbuf requires 64 bytes of RAM. 177 | #define MEMP_NUM_NETBUF MBED_CONF_LWIP_NUM_NETBUF 178 | 179 | // One netconn is needed for each UDPSocket or TCPSocket. 180 | // Each requires 236 bytes of RAM (total rounded to multiple of 512). 181 | #define MEMP_NUM_NETCONN MBED_CONF_LWIP_SOCKET_MAX 182 | 183 | #if MBED_CONF_LWIP_TCP_ENABLED 184 | #define LWIP_TCP 1 185 | #define TCP_OVERSIZE 0 186 | #define LWIP_TCP_KEEPALIVE 1 187 | 188 | #define TCP_CLOSE_TIMEOUT MBED_CONF_LWIP_TCP_CLOSE_TIMEOUT 189 | 190 | #else 191 | #define LWIP_TCP 0 192 | #endif 193 | 194 | #define LWIP_DNS 1 195 | // Only DNS address storage is enabled 196 | #define LWIP_FULL_DNS 0 197 | #define LWIP_SOCKET 0 198 | 199 | #define SO_REUSE 1 200 | 201 | // Support Multicast 202 | #include "stdlib.h" 203 | #define LWIP_IGMP LWIP_IPV4 204 | #define LWIP_RAND() lwip_get_random() 205 | 206 | #define LWIP_COMPAT_SOCKETS 0 207 | #define LWIP_POSIX_SOCKETS_IO_NAMES 0 208 | 209 | #define LWIP_BROADCAST_PING 1 210 | 211 | // Fragmentation on, as per IPv4 default 212 | #define LWIP_IPV6_FRAG LWIP_IPV6 213 | 214 | // Queuing, default is "disabled", as per IPv4 default (so actually queues 1) 215 | #define LWIP_ND6_QUEUEING MBED_CONF_ND6_QUEUEING 216 | 217 | // Debug Options 218 | #define NETIF_DEBUG LWIP_DBG_OFF 219 | #define PBUF_DEBUG LWIP_DBG_OFF 220 | #define API_LIB_DEBUG LWIP_DBG_OFF 221 | #define API_MSG_DEBUG LWIP_DBG_OFF 222 | #define SOCKETS_DEBUG LWIP_DBG_OFF 223 | #define ICMP_DEBUG LWIP_DBG_OFF 224 | #define IGMP_DEBUG LWIP_DBG_OFF 225 | #define INET_DEBUG LWIP_DBG_OFF 226 | #define IP_DEBUG LWIP_DBG_OFF 227 | #define IP_REASS_DEBUG LWIP_DBG_OFF 228 | #define RAW_DEBUG LWIP_DBG_OFF 229 | #define MEM_DEBUG LWIP_DBG_OFF 230 | #define MEMP_DEBUG LWIP_DBG_OFF 231 | #define SYS_DEBUG LWIP_DBG_OFF 232 | #define TIMERS_DEBUG LWIP_DBG_OFF 233 | #define TCP_DEBUG LWIP_DBG_OFF 234 | #define TCP_INPUT_DEBUG LWIP_DBG_OFF 235 | #define TCP_FR_DEBUG LWIP_DBG_OFF 236 | #define TCP_RTO_DEBUG LWIP_DBG_OFF 237 | #define TCP_CWND_DEBUG LWIP_DBG_OFF 238 | #define TCP_WND_DEBUG LWIP_DBG_OFF 239 | #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 240 | #define TCP_RST_DEBUG LWIP_DBG_OFF 241 | #define TCP_QLEN_DEBUG LWIP_DBG_OFF 242 | #define UDP_DEBUG LWIP_DBG_OFF 243 | #define TCPIP_DEBUG LWIP_DBG_OFF 244 | #define SLIP_DEBUG LWIP_DBG_OFF 245 | #define DHCP_DEBUG LWIP_DBG_OFF 246 | #define AUTOIP_DEBUG LWIP_DBG_OFF 247 | #define DNS_DEBUG LWIP_DBG_OFF 248 | #define IP6_DEBUG LWIP_DBG_OFF 249 | 250 | #define ETHARP_DEBUG LWIP_DBG_OFF 251 | #define UDP_LPC_EMAC LWIP_DBG_OFF 252 | 253 | #ifdef LWIP_DEBUG 254 | #define MEMP_OVERFLOW_CHECK 1 255 | #define MEMP_SANITY_CHECK 1 256 | #define LWIP_DBG_TYPES_ON LWIP_DBG_ON 257 | #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL 258 | #else 259 | #define LWIP_NOASSERT 1 260 | #define LWIP_STATS 0 261 | #endif 262 | 263 | #define TRACE_TO_ASCII_HEX_DUMP 0 264 | 265 | #define LWIP_PLATFORM_BYTESWAP 1 266 | 267 | #define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 268 | 269 | // Interface type configuration 270 | 271 | #if MBED_CONF_LWIP_ETHERNET_ENABLED 272 | #define LWIP_ARP 1 273 | #define LWIP_ETHERNET 1 274 | #define LWIP_DHCP LWIP_IPV4 275 | #else 276 | #define LWIP_ARP 0 277 | #define LWIP_ETHERNET 0 278 | #endif // MBED_CONF_LWIP_ETHERNET_ENABLED 279 | 280 | #if MBED_CONF_LWIP_L3IP_ENABLED 281 | #define LWIP_L3IP 1 282 | #else 283 | #define LWIP_L3IP 0 284 | #endif 285 | 286 | //Maximum size of network interface name 287 | #define INTERFACE_NAME_MAX_SIZE NSAPI_INTERFACE_NAME_MAX_SIZE 288 | // Note generic macro name used rather than MBED_CONF_LWIP_PPP_ENABLED 289 | // to allow users like PPPCellularInterface to detect that nsapi_ppp.h is available. 290 | 291 | // Enable PPP for now either from lwIP PPP configuration (obsolete) or from PPP service configuration 292 | #if MBED_CONF_PPP_ENABLED || MBED_CONF_LWIP_PPP_ENABLED 293 | 294 | #define PPP_SUPPORT 1 295 | 296 | #if MBED_CONF_PPP_IPV4_ENABLED || MBED_CONF_LWIP_IPV4_ENABLED 297 | #define LWIP 0x11991199 298 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV4_ENABLED 299 | #error LWIP: IPv4 PPP enabled but not IPv4 300 | #endif 301 | #undef LWIP 302 | #define PPP_IPV4_SUPPORT 1 303 | #endif 304 | 305 | #if MBED_CONF_PPP_IPV6_ENABLED || MBED_CONF_LWIP_IPV6_ENABLED 306 | #define LWIP 0x11991199 307 | #if (MBED_CONF_NSAPI_DEFAULT_STACK == LWIP) && !MBED_CONF_LWIP_IPV6_ENABLED 308 | #error LWIP: IPv6 PPP enabled but not IPv6 309 | #endif 310 | #undef LWIP 311 | #define PPP_IPV6_SUPPORT 1 312 | // Later to be dynamic for use for multiple interfaces 313 | #define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 314 | #endif 315 | 316 | #endif 317 | 318 | #define LWIP_NETBUF_RECVINFO MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED 319 | 320 | // Make sure we default these to off, so 321 | // LWIP doesn't default to on 322 | #ifndef LWIP_ARP 323 | #define LWIP_ARP 0 324 | #endif 325 | 326 | // Checksum-on-copy disabled due to https://savannah.nongnu.org/bugs/?50914 327 | #define LWIP_CHECKSUM_ON_COPY 0 328 | 329 | #define LWIP_NETIF_HOSTNAME 1 330 | #define LWIP_NETIF_STATUS_CALLBACK 1 331 | #define LWIP_NETIF_LINK_CALLBACK 1 332 | 333 | #define DNS_TABLE_SIZE 2 334 | #define DNS_MAX_NAME_LENGTH 128 335 | 336 | #include "lwip_random.h" 337 | #include "lwip_tcp_isn.h" 338 | #define LWIP_HOOK_TCP_ISN lwip_hook_tcp_isn 339 | #ifdef MBEDTLS_MD5_C 340 | #define LWIP_USE_EXTERNAL_MBEDTLS 1 341 | #else 342 | #define LWIP_USE_EXTERNAL_MBEDTLS 0 343 | #endif 344 | 345 | #define LWIP_ND6_RDNSS_MAX_DNS_SERVERS MBED_CONF_LWIP_ND6_RDNSS_MAX_DNS_SERVERS 346 | 347 | #endif /* LWIPOPTS_H_ */ 348 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.7.2/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/2.8.0/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/3.0.0/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/3.0.1/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/3.1.1/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /Packages_Patches/arduino/hardware/mbed_portenta/3.4.1/portenta_post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | portenta_h7_rules () { 4 | echo "" 5 | echo "# Portenta H7 bootloader mode UDEV rules" 6 | echo "" 7 | cat < /etc/udev/rules.d/49-portenta_h7.rules 18 | 19 | # reload udev rules 20 | echo "Reload rules..." 21 | udevadm trigger 22 | udevadm control --reload-rules 23 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Portenta_H7_TimerInterrupt Library 2 | 3 | [![arduino-library-badge](https://www.ardu-badge.com/badge/Portenta_H7_TimerInterrupt.svg?)](https://www.ardu-badge.com/Portenta_H7_TimerInterrupt) 4 | [![GitHub release](https://img.shields.io/github/release/khoih-prog/Portenta_H7_TimerInterrupt.svg)](https://github.com/khoih-prog/Portenta_H7_TimerInterrupt/releases) 5 | [![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/Portenta_H7_TimerInterrupt/blob/master/LICENSE) 6 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) 7 | [![GitHub issues](https://img.shields.io/github/issues/khoih-prog/Portenta_H7_TimerInterrupt.svg)](http://github.com/khoih-prog/Portenta_H7_TimerInterrupt/issues) 8 | 9 | 10 | Donate to my libraries using BuyMeACoffee 11 | 12 | 13 | 14 | --- 15 | --- 16 | 17 | ## Table of Contents 18 | 19 | * [Changelog](#changelog) 20 | * [Releases v1.4.0](#Releases-v140) 21 | * [Releases v1.3.1](#Releases-v131) 22 | * [Releases v1.3.0](#Releases-v130) 23 | * [Initial Releases v1.2.1](#Initial-Releases-v121) 24 | 25 | --- 26 | --- 27 | 28 | ## Changelog 29 | 30 | ### Releases v1.4.0 31 | 32 | 1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories 33 | 2. Add example [multiFileProject](examples/multiFileProject) to demo for multiple-file project. 34 | 3. Fix `reattachInterrupt()` bug. Check [bugfix: reattachInterrupt() pass wrong frequency value to setFrequency() #19](https://github.com/khoih-prog/ESP8266TimerInterrupt/pull/19) 35 | 4. Optimize library code by using `reference-passing` instead of `value-passing` 36 | 5. Update all examples 37 | 6. Update `Packages_Patches` 38 | 39 | ### Releases v1.3.1 40 | 41 | 1. Fix warnings in PWM examples 42 | 43 | ### Releases v1.3.0 44 | 45 | 1. Add PWM features and examples 46 | 47 | ### Initial Releases v1.2.1 48 | 49 | 1. Initial coding to support **Portenta_H7 boards** such as Portenta_H7 Rev2 ABX00042, etc., using [**ArduinoCore-mbed mbed_portenta** core](https://github.com/arduino/ArduinoCore-mbed) 50 | 2. Permit up to 16 super-long-time, super-accurate ISR-based timers to avoid being blocked 51 | 3. Using cpp code besides Impl.h code to use if Multiple-Definition linker error. 52 | 4. Bump version to v1.2.1 to sync with [STM32_TimerInterrupt library](https://github.com/khoih-prog/STM32_TimerInterrupt) 53 | 54 | -------------------------------------------------------------------------------- /examples/Argument_None/Argument_None.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Argument_None.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | 16 | /* 17 | Notes: 18 | Special design is necessary to share data between interrupt code and the rest of your program. 19 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 20 | variable can not spontaneously change. Because your function may change variables while your program is using them, 21 | the compiler needs this hint. But volatile alone is often not enough. 22 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 23 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 24 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 25 | or the entire sequence of your code which accesses the data. 26 | */ 27 | 28 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 29 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 30 | #endif 31 | 32 | // These define's must be placed at the beginning before #include "Portenta_H7_TimerInterrupt.h" 33 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 34 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 35 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 36 | 37 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 38 | #include "Portenta_H7_TimerInterrupt.h" 39 | 40 | #define LED_OFF HIGH 41 | #define LED_ON LOW 42 | 43 | #ifndef LED_BUILTIN 44 | #define LED_BUILTIN 24 //LEDG // Pin 24 control on-board LED_GREEN on Portenta_H7 45 | #endif 46 | 47 | #ifndef LED_BLUE 48 | #define LED_BLUE 25 //LEDB // Pin 25 control on-board LED_BLUE on Portenta_H7 49 | #endif 50 | 51 | #ifndef LED_RED 52 | #define LED_RED 23 // LEDR // Pin 23 control on-board LED_RED on Portenta_H7 53 | #endif 54 | 55 | // In Portenta_H7, avoid doing something fancy in ISR, for example Serial.print 56 | // Or you can get this run-time error / crash 57 | 58 | void TimerHandler0() 59 | { 60 | static bool toggle0 = false; 61 | 62 | //timer interrupt toggles pin LED_BUILTIN 63 | digitalWrite(LED_BUILTIN, toggle0); 64 | toggle0 = !toggle0; 65 | } 66 | 67 | void TimerHandler1() 68 | { 69 | static bool toggle1 = false; 70 | 71 | //timer interrupt toggles outputPin 72 | digitalWrite(LED_BLUE, toggle1); 73 | toggle1 = !toggle1; 74 | } 75 | 76 | void TimerHandler2() 77 | { 78 | static bool toggle2 = false; 79 | 80 | //timer interrupt toggles outputPin 81 | digitalWrite(LED_RED, toggle2); 82 | toggle2 = !toggle2; 83 | } 84 | 85 | #define TIMER0_INTERVAL_MS 1000 86 | #define TIMER1_INTERVAL_MS 2000 87 | #define TIMER2_INTERVAL_MS 5000 88 | 89 | // Depending on the board, you can select STM32H7 Hardware Timer from TIM1-TIM22 90 | // If you select a Timer not correctly, you'll get a message from compiler 91 | // 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? 92 | 93 | // Portenta_H7 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 94 | // Portenta_H7 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 95 | // Portenta_H7 No timer : TIM9, TIM10, TIM11. Only for STM32F2, STM32F4 and STM32L1 96 | // Portenta_H7 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 97 | 98 | // Init timer TIM15 99 | Portenta_H7_Timer ITimer0(TIM15); 100 | // Init timer TIM16 101 | Portenta_H7_Timer ITimer1(TIM16); 102 | // Init timer TIM17 103 | Portenta_H7_Timer ITimer2(TIM17); 104 | 105 | void setup() 106 | { 107 | pinMode(LED_BUILTIN, OUTPUT); 108 | pinMode(LED_BLUE, OUTPUT); 109 | pinMode(LED_RED, OUTPUT); 110 | 111 | digitalWrite(LED_BUILTIN, LED_OFF); 112 | digitalWrite(LED_BLUE, LED_OFF); 113 | digitalWrite(LED_RED, LED_OFF); 114 | 115 | 116 | Serial.begin(115200); 117 | while (!Serial); 118 | 119 | delay(100); 120 | 121 | Serial.print(F("\nStarting Argument_None on ")); Serial.println(BOARD_NAME); 122 | Serial.println(PORTENTA_H7_TIMER_INTERRUPT_VERSION); 123 | 124 | // Interval in microsecs 125 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 126 | { 127 | Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis()); 128 | } 129 | else 130 | Serial.println(F("Can't set ITimer0. Select another freq. or timer")); 131 | 132 | // Interval in microsecs 133 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 134 | { 135 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 136 | } 137 | else 138 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 139 | 140 | // Interval in microsecs 141 | if (ITimer2.attachInterruptInterval(TIMER2_INTERVAL_MS * 1000, TimerHandler2)) 142 | { 143 | Serial.print(F("Starting ITimer2 OK, millis() = ")); Serial.println(millis()); 144 | } 145 | else 146 | Serial.println(F("Can't set ITimer2. Select another freq. or timer")); 147 | } 148 | 149 | void loop() 150 | { 151 | 152 | } 153 | -------------------------------------------------------------------------------- /examples/Change_Interval/Change_Interval.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Change_Interval.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | 16 | /* 17 | Notes: 18 | Special design is necessary to share data between interrupt code and the rest of your program. 19 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 20 | variable can not spontaneously change. Because your function may change variables while your program is using them, 21 | the compiler needs this hint. But volatile alone is often not enough. 22 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 23 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 24 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 25 | or the entire sequence of your code which accesses the data. 26 | */ 27 | 28 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 29 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 30 | #endif 31 | 32 | // These define's must be placed at the beginning before #include "Portenta_H7_TimerInterrupt.h" 33 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 34 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 35 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 36 | 37 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 38 | #include "Portenta_H7_TimerInterrupt.h" 39 | 40 | #define LED_OFF HIGH 41 | #define LED_ON LOW 42 | 43 | #ifndef LED_BUILTIN 44 | #define LED_BUILTIN 24 //LEDG // Pin 24 control on-board LED_GREEN on Portenta_H7 45 | #endif 46 | 47 | #ifndef LED_BLUE 48 | #define LED_BLUE 25 //LEDB // Pin 25 control on-board LED_BLUE on Portenta_H7 49 | #endif 50 | 51 | #ifndef LED_RED 52 | #define LED_RED 23 // LEDR // Pin 23 control on-board LED_RED on Portenta_H7 53 | #endif 54 | 55 | #define TIMER0_INTERVAL_MS 500 56 | #define TIMER1_INTERVAL_MS 1000 57 | 58 | volatile uint32_t Timer0Count = 0; 59 | volatile uint32_t Timer1Count = 0; 60 | 61 | // Depending on the board, you can select STM32H7 Hardware Timer from TIM1-TIM22 62 | // If you select a Timer not correctly, you'll get a message from compiler 63 | // 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? 64 | 65 | // Portenta_H7 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 66 | // Portenta_H7 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 67 | // Portenta_H7 No timer : TIM9, TIM10, TIM11. Only for STM32F2, STM32F4 and STM32L1 68 | // Portenta_H7 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 69 | 70 | // Init timer TIM15 71 | Portenta_H7_Timer ITimer0(TIM15); 72 | // Init timer TIM16 73 | Portenta_H7_Timer ITimer1(TIM16); 74 | 75 | void printResult(uint32_t currTime) 76 | { 77 | Serial.print(F("Time = ")); Serial.print(currTime); 78 | Serial.print(F(", Timer0Count = ")); Serial.print(Timer0Count); 79 | Serial.print(F(", Timer1Count = ")); Serial.println(Timer1Count); 80 | } 81 | 82 | // In Portenta_H7, avoid doing something fancy in ISR, for example Serial.print 83 | // Or you can get this run-time error / crash 84 | 85 | void TimerHandler0() 86 | { 87 | static bool toggle0 = false; 88 | 89 | // Flag for checking to be sure ISR is working as SErial.print is not OK here in ISR 90 | Timer0Count++; 91 | 92 | //timer interrupt toggles pin LED_BUILTIN 93 | digitalWrite(LED_BUILTIN, toggle0); 94 | toggle0 = !toggle0; 95 | } 96 | 97 | void TimerHandler1() 98 | { 99 | static bool toggle1 = false; 100 | 101 | // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR 102 | Timer1Count++; 103 | 104 | //timer interrupt toggles outputPin 105 | digitalWrite(LED_BLUE, toggle1); 106 | toggle1 = !toggle1; 107 | } 108 | 109 | void setup() 110 | { 111 | pinMode(LED_BUILTIN, OUTPUT); 112 | pinMode(LED_BLUE, OUTPUT); 113 | 114 | Serial.begin(115200); 115 | while (!Serial); 116 | 117 | delay(100); 118 | 119 | Serial.print(F("\nStarting Change_Interval on ")); Serial.println(BOARD_NAME); 120 | Serial.println(PORTENTA_H7_TIMER_INTERRUPT_VERSION); 121 | 122 | // Interval in microsecs 123 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 124 | { 125 | Serial.print(F("Starting Timer0 OK, millis() = ")); Serial.println(millis()); 126 | } 127 | else 128 | Serial.println(F("Can't set ITimer0. Select another freq. or timer")); 129 | 130 | // Interval in microsecs 131 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 132 | { 133 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 134 | } 135 | else 136 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 137 | } 138 | 139 | #define CHECK_INTERVAL_MS 10000L 140 | #define CHANGE_INTERVAL_MS 20000L 141 | 142 | void loop() 143 | { 144 | static uint32_t lastTime = 0; 145 | static uint32_t lastChangeTime = 0; 146 | static uint32_t currTime; 147 | static uint32_t multFactor = 0; 148 | 149 | currTime = millis(); 150 | 151 | if (currTime - lastTime > CHECK_INTERVAL_MS) 152 | { 153 | printResult(currTime); 154 | lastTime = currTime; 155 | 156 | if (currTime - lastChangeTime > CHANGE_INTERVAL_MS) 157 | { 158 | //setInterval(unsigned long interval, timerCallback callback) 159 | multFactor = (multFactor + 1) % 2; 160 | 161 | ITimer0.setInterval(TIMER0_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler0); 162 | ITimer1.setInterval(TIMER1_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler1); 163 | 164 | Serial.print(F("Changing Interval, Timer0 = ")); Serial.print(TIMER0_INTERVAL_MS * (multFactor + 1)); 165 | Serial.print(F(", Timer1 = ")); Serial.println(TIMER1_INTERVAL_MS * (multFactor + 1)); 166 | 167 | lastChangeTime = currTime; 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | ISR_16_Timers_Array.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | /* 16 | Notes: 17 | Special design is necessary to share data between interrupt code and the rest of your program. 18 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 19 | variable can not spontaneously change. Because your function may change variables while your program is using them, 20 | the compiler needs this hint. But volatile alone is often not enough. 21 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 22 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 23 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 24 | or the entire sequence of your code which accesses the data. 25 | */ 26 | 27 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 28 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 29 | #endif 30 | 31 | // These define's must be placed at the beginning before #include "Portenta_H7_TimerInterrupt.h" 32 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 33 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 34 | #define TIMER_INTERRUPT_DEBUG 1 35 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 36 | 37 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 38 | #include "Portenta_H7_TimerInterrupt.h" 39 | 40 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 41 | #include "Portenta_H7_ISR_Timer.h" 42 | 43 | #include // https://github.com/jfturcot/SimpleTimer 44 | 45 | #define LED_OFF HIGH 46 | #define LED_ON LOW 47 | 48 | #ifndef LED_BUILTIN 49 | #define LED_BUILTIN 24 //LEDG // Pin 24 control on-board LED_GREEN on Portenta_H7 50 | #endif 51 | 52 | #ifndef LED_BLUE 53 | #define LED_BLUE 25 //LEDB // Pin 25 control on-board LED_BLUE on Portenta_H7 54 | #endif 55 | 56 | #ifndef LED_RED 57 | #define LED_RED 23 // LEDR // Pin 23 control on-board LED_RED on Portenta_H7 58 | #endif 59 | 60 | #define HW_TIMER_INTERVAL_US 100L 61 | 62 | volatile uint32_t startMillis = 0; 63 | 64 | // Depending on the board, you can select STM32H7 Hardware Timer from TIM1-TIM22 65 | // If you select a Timer not correctly, you'll get a message from compiler 66 | // 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? 67 | 68 | // Portenta_H7 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 69 | // Portenta_H7 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 70 | // Portenta_H7 No timer : TIM9, TIM10, TIM11. Only for STM32F2, STM32F4 and STM32L1 71 | // Portenta_H7 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 72 | 73 | // Init timer TIM15 74 | Portenta_H7_Timer ITimer(TIM15); 75 | 76 | // Init Portenta_H7_ISR_Timer 77 | // Each Portenta_H7_ISR_Timer can service 16 different ISR-based timers 78 | Portenta_H7_ISR_Timer ISR_Timer; 79 | 80 | #define LED_TOGGLE_INTERVAL_MS 2000L 81 | 82 | // In Portenta_H7, avoid doing something fancy in ISR, for example Serial.print 83 | // Or you can get this run-time error / crash 84 | 85 | void TimerHandler() 86 | { 87 | static bool toggle = false; 88 | static int timeRun = 0; 89 | 90 | ISR_Timer.run(); 91 | 92 | // Toggle LED every LED_TOGGLE_INTERVAL_MS = 5000ms = 5s 93 | if (++timeRun == ( (LED_TOGGLE_INTERVAL_MS * 1000 ) / HW_TIMER_INTERVAL_US) ) 94 | { 95 | timeRun = 0; 96 | 97 | //timer interrupt toggles pin LED_BUILTIN 98 | digitalWrite(LED_BUILTIN, toggle); 99 | toggle = !toggle; 100 | } 101 | } 102 | 103 | #define NUMBER_ISR_TIMERS 16 104 | 105 | volatile unsigned long deltaMillis [NUMBER_ISR_TIMERS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 106 | volatile unsigned long previousMillis [NUMBER_ISR_TIMERS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 107 | 108 | // You can assign any interval for any timer here, in milliseconds 109 | uint32_t TimerInterval[NUMBER_ISR_TIMERS] = 110 | { 111 | 1000L, 2000L, 3000L, 4000L, 5000L, 6000L, 7000L, 8000L, 112 | 9000L, 10000L, 11000L, 12000L, 13000L, 14000L, 15000L, 16000L 113 | }; 114 | 115 | typedef void (*irqCallback) (); 116 | 117 | #if (TIMER_INTERRUPT_DEBUG > 0) 118 | void printStatus(uint16_t index, unsigned long deltaMillis, unsigned long currentMillis) 119 | { 120 | Serial.print(TimerInterval[index]/1000); Serial.print("s: Delta ms = "); Serial.print(deltaMillis); 121 | Serial.print(", ms = "); Serial.println(currentMillis); 122 | } 123 | #endif 124 | 125 | void doingSomething(int index) 126 | { 127 | unsigned long currentMillis = millis(); 128 | 129 | deltaMillis[index] = currentMillis - previousMillis[index]; 130 | previousMillis[index] = currentMillis; 131 | } 132 | 133 | // In Portenta_H7, avoid doing something fancy in ISR, for example complex Serial.print with String() argument 134 | // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment 135 | // Or you can get this run-time error / crash 136 | void doingSomething0() 137 | { 138 | doingSomething(0); 139 | } 140 | 141 | void doingSomething1() 142 | { 143 | doingSomething(1); 144 | } 145 | 146 | void doingSomething2() 147 | { 148 | doingSomething(2); 149 | } 150 | 151 | void doingSomething3() 152 | { 153 | doingSomething(3); 154 | } 155 | 156 | void doingSomething4() 157 | { 158 | doingSomething(4); 159 | } 160 | 161 | void doingSomething5() 162 | { 163 | doingSomething(5); 164 | } 165 | 166 | void doingSomething6() 167 | { 168 | doingSomething(6); 169 | } 170 | 171 | void doingSomething7() 172 | { 173 | doingSomething(7); 174 | } 175 | 176 | void doingSomething8() 177 | { 178 | doingSomething(8); 179 | } 180 | 181 | void doingSomething9() 182 | { 183 | doingSomething(9); 184 | } 185 | 186 | void doingSomething10() 187 | { 188 | doingSomething(10); 189 | } 190 | 191 | void doingSomething11() 192 | { 193 | doingSomething(11); 194 | } 195 | 196 | void doingSomething12() 197 | { 198 | doingSomething(12); 199 | } 200 | 201 | void doingSomething13() 202 | { 203 | doingSomething(13); 204 | } 205 | 206 | void doingSomething14() 207 | { 208 | doingSomething(14); 209 | } 210 | 211 | void doingSomething15() 212 | { 213 | doingSomething(15); 214 | } 215 | 216 | irqCallback irqCallbackFunc[NUMBER_ISR_TIMERS] = 217 | { 218 | doingSomething0, doingSomething1, doingSomething2, doingSomething3, 219 | doingSomething4, doingSomething5, doingSomething6, doingSomething7, 220 | doingSomething8, doingSomething9, doingSomething10, doingSomething11, 221 | doingSomething12, doingSomething13, doingSomething14, doingSomething15 222 | }; 223 | 224 | //////////////////////////////////////////////// 225 | 226 | 227 | #define SIMPLE_TIMER_MS 2000L 228 | 229 | // Init SimpleTimer 230 | SimpleTimer simpleTimer; 231 | 232 | // Here is software Timer, you can do somewhat fancy stuffs without many issues. 233 | // But always avoid 234 | // 1. Long delay() it just doing nothing and pain-without-gain wasting CPU power.Plan and design your code / strategy ahead 235 | // 2. Very long "do", "while", "for" loops without predetermined exit time. 236 | void simpleTimerDoingSomething2s() 237 | { 238 | static unsigned long previousMillis = startMillis; 239 | 240 | Serial.print(F("simpleTimerDoingSomething2s: Delta programmed ms = ")); Serial.print(SIMPLE_TIMER_MS); 241 | Serial.print(F(", actual = ")); Serial.println(millis() - previousMillis); 242 | 243 | for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++) 244 | { 245 | Serial.print(F("Timer : ")); Serial.print(i); 246 | Serial.print(F(", programmed : ")); Serial.print(TimerInterval[i]); 247 | Serial.print(F(", actual : ")); Serial.println(deltaMillis[i]); 248 | } 249 | 250 | previousMillis = millis(); 251 | } 252 | 253 | void setup() 254 | { 255 | pinMode(LED_BUILTIN, OUTPUT); 256 | digitalWrite(LED_BUILTIN, LED_OFF); 257 | 258 | Serial.begin(115200); 259 | while (!Serial); 260 | 261 | delay(100); 262 | 263 | Serial.print(F("\nStarting ISR_16_Timers_Array on ")); Serial.println(BOARD_NAME); 264 | Serial.println(PORTENTA_H7_TIMER_INTERRUPT_VERSION); 265 | 266 | // Interval in microsecs 267 | if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler)) 268 | { 269 | startMillis = millis(); 270 | Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(startMillis); 271 | } 272 | else 273 | Serial.println(F("Can't set ITimer correctly. Select another freq. or interval")); 274 | 275 | startMillis = millis(); 276 | 277 | // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary 278 | // You can use up to 16 timer for each STM32_ISR_Timer 279 | for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++) 280 | { 281 | previousMillis[i] = millis(); 282 | ISR_Timer.setInterval(TimerInterval[i], irqCallbackFunc[i]); 283 | } 284 | 285 | // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary. 286 | simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s); 287 | } 288 | 289 | #define BLOCKING_TIME_MS 10000L 290 | 291 | void loop() 292 | { 293 | // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer 294 | // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer 295 | // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS) 296 | // While that of ISR_Timer is still prefect. 297 | delay(BLOCKING_TIME_MS); 298 | 299 | // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary 300 | // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer. 301 | simpleTimer.run(); 302 | } 303 | -------------------------------------------------------------------------------- /examples/SwitchDebounce/SwitchDebounce.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | SwitchDebounce.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | /* 16 | Notes: 17 | Special design is necessary to share data between interrupt code and the rest of your program. 18 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 19 | variable can not spontaneously change. Because your function may change variables while your program is using them, 20 | the compiler needs this hint. But volatile alone is often not enough. 21 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 22 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 23 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 24 | or the entire sequence of your code which accesses the data. 25 | 26 | Switch Debouncing uses high frequency hardware timer 50Hz == 20ms) to measure the time from the SW is pressed, 27 | debouncing time is 100ms => SW is considered pressed if timer count is > 5, then call / flag SW is pressed 28 | When the SW is released, timer will count (debounce) until more than 50ms until consider SW is released. 29 | We can set to flag or call a function whenever SW is pressed more than certain predetermined time, even before 30 | SW is released. 31 | */ 32 | 33 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 34 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 35 | #endif 36 | 37 | // These define's must be placed at the beginning before #include "Portenta_H7_TimerInterrupt.h" 38 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 39 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 40 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 41 | 42 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 43 | #include "Portenta_H7_TimerInterrupt.h" 44 | 45 | #define LED_OFF HIGH 46 | #define LED_ON LOW 47 | 48 | #ifndef LED_BUILTIN 49 | #define LED_BUILTIN 24 //LEDG // Pin 24 control on-board LED_GREEN on Portenta_H7 50 | #endif 51 | 52 | #ifndef LED_BLUE 53 | #define LED_BLUE 25 //LEDB // Pin 25 control on-board LED_BLUE on Portenta_H7 54 | #endif 55 | 56 | #ifndef LED_RED 57 | #define LED_RED 23 // LEDR // Pin 23 control on-board LED_RED on Portenta_H7 58 | #endif 59 | 60 | unsigned int SWPin = D5; 61 | 62 | #define TIMER1_INTERVAL_MS 20 63 | #define DEBOUNCING_INTERVAL_MS 100 64 | #define LONG_PRESS_INTERVAL_MS 5000 65 | 66 | #define LOCAL_DEBUG 1 67 | 68 | // Depending on the board, you can select STM32H7 Hardware Timer from TIM1-TIM22 69 | // If you select a Timer not correctly, you'll get a message from compiler 70 | // 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? 71 | 72 | // Portenta_H7 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 73 | // Portenta_H7 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 74 | // Portenta_H7 No timer : TIM9, TIM10, TIM11. Only for STM32F2, STM32F4 and STM32L1 75 | // Portenta_H7 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 76 | 77 | // Init timer TIM14 78 | Portenta_H7_Timer ITimer(TIM14); 79 | 80 | volatile bool SWPressed = false; 81 | volatile bool SWLongPressed = false; 82 | 83 | void Your_Response_To_Press() 84 | { 85 | digitalWrite(LED_BUILTIN, LED_ON); 86 | } 87 | 88 | void Your_Response_To_Release() 89 | { 90 | digitalWrite(LED_BUILTIN, LED_OFF); 91 | } 92 | 93 | // In Portenta_H7, avoid doing something fancy in ISR, for example Serial.print 94 | // Or you can get this run-time error / crash 95 | 96 | void TimerHandler() 97 | { 98 | static unsigned int debounceCountSWPressed = 0; 99 | static unsigned int debounceCountSWReleased = 0; 100 | 101 | if ( (!digitalRead(SWPin)) ) 102 | { 103 | // Start debouncing counting debounceCountSWPressed and clear debounceCountSWReleased 104 | debounceCountSWReleased = 0; 105 | 106 | if (++debounceCountSWPressed >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS) 107 | { 108 | // Call and flag SWPressed 109 | if (!SWPressed) 110 | { 111 | SWPressed = true; 112 | // Do something for SWPressed here in ISR 113 | // But it's better to use outside software timer to do your job instead of inside ISR 114 | Your_Response_To_Press(); 115 | } 116 | 117 | if (debounceCountSWPressed >= LONG_PRESS_INTERVAL_MS / TIMER1_INTERVAL_MS) 118 | { 119 | // Call and flag SWLongPressed 120 | if (!SWLongPressed) 121 | { 122 | SWLongPressed = true; 123 | // Do something for SWLongPressed here in ISR 124 | // But it's better to use outside software timer to do your job instead of inside ISR 125 | //Your_Response_To_Long_Press(); 126 | } 127 | } 128 | } 129 | } 130 | else 131 | { 132 | // Start debouncing counting debounceCountSWReleased and clear debounceCountSWPressed 133 | if ( SWPressed && (++debounceCountSWReleased >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS)) 134 | { 135 | SWPressed = false; 136 | SWLongPressed = false; 137 | 138 | // Do something for !SWPressed here in ISR 139 | // But it's better to use outside software timer to do your job instead of inside ISR 140 | Your_Response_To_Release(); 141 | 142 | // Call and flag SWPressed 143 | 144 | debounceCountSWPressed = 0; 145 | } 146 | } 147 | } 148 | 149 | void setup() 150 | { 151 | pinMode(SWPin, INPUT_PULLUP); 152 | pinMode(LED_BUILTIN, OUTPUT); 153 | 154 | digitalWrite(LED_BUILTIN, LED_OFF); 155 | 156 | Serial.begin(115200); 157 | while (!Serial); 158 | 159 | delay(100); 160 | 161 | Serial.print(F("\nStarting SwitchDebounce on ")); Serial.println(BOARD_NAME); 162 | Serial.println(PORTENTA_H7_TIMER_INTERRUPT_VERSION); 163 | 164 | // Interval in microsecs 165 | if (ITimer.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler)) 166 | { 167 | Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis()); 168 | } 169 | else 170 | Serial.println(F("Can't set ITimer. Select another freq. or timer")); 171 | } 172 | 173 | void loop() 174 | { 175 | 176 | } 177 | -------------------------------------------------------------------------------- /examples/TimerInterruptLEDDemo/TimerInterruptLEDDemo.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | TimerInterruptLEDDemo.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | 16 | /* 17 | Notes: 18 | Special design is necessary to share data between interrupt code and the rest of your program. 19 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 20 | variable can not spontaneously change. Because your function may change variables while your program is using them, 21 | the compiler needs this hint. But volatile alone is often not enough. 22 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 23 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 24 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 25 | or the entire sequence of your code which accesses the data. 26 | */ 27 | 28 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 29 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 30 | #endif 31 | 32 | // These define's must be placed at the beginning before #include "Portenta_H7_TimerInterrupt.h" 33 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 34 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 35 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 36 | 37 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 38 | #include "Portenta_H7_TimerInterrupt.h" 39 | 40 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 41 | #include "Portenta_H7_ISR_Timer.h" 42 | 43 | #define LED_OFF HIGH 44 | #define LED_ON LOW 45 | 46 | #ifndef LED_BUILTIN 47 | #define LED_BUILTIN 24 //LEDG // Pin 24 control on-board LED_GREEN on Portenta_H7 48 | #endif 49 | 50 | #ifndef LED_BLUE 51 | #define LED_BLUE 25 //LEDB // Pin 25 control on-board LED_BLUE on Portenta_H7 52 | #endif 53 | 54 | #ifndef LED_RED 55 | #define LED_RED 23 // LEDR // Pin 23 control on-board LED_RED on Portenta_H7 56 | #endif 57 | 58 | #define TIMER_INTERVAL_MS 100 59 | #define HW_TIMER_INTERVAL_MS 50 60 | 61 | // Depending on the board, you can select STM32H7 Hardware Timer from TIM1-TIM22 62 | // If you select a Timer not correctly, you'll get a message from compiler 63 | // 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? 64 | 65 | // Portenta_H7 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 66 | // Portenta_H7 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 67 | // Portenta_H7 No timer : TIM9, TIM10, TIM11. Only for STM32F2, STM32F4 and STM32L1 68 | // Portenta_H7 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 69 | 70 | // Init timer TIM12 71 | Portenta_H7_Timer ITimer(TIM12); 72 | 73 | 74 | // Init Portenta_H7_ISR_Timer 75 | // Each Portenta_H7_ISR_Timer can service 16 different ISR-based timers 76 | Portenta_H7_ISR_Timer ISR_Timer; 77 | 78 | #define TIMER_INTERVAL_0_5S 500L 79 | #define TIMER_INTERVAL_1S 1000L 80 | #define TIMER_INTERVAL_1_5S 1500L 81 | 82 | // In Portenta_H7, avoid doing something fancy in ISR, for example Serial.print 83 | // Or you can get this run-time error / crash 84 | 85 | void TimerHandler() 86 | { 87 | ISR_Timer.run(); 88 | } 89 | 90 | // In STM32, avoid doing something fancy in ISR, for example complex Serial.print with String() argument 91 | // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment 92 | // Or you can get this run-time error / crash 93 | void doingSomething1() 94 | { 95 | digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); 96 | } 97 | 98 | void doingSomething2() 99 | { 100 | digitalWrite(LED_BLUE, !digitalRead(LED_BLUE)); 101 | } 102 | void doingSomething3() 103 | { 104 | digitalWrite(LED_RED, !digitalRead(LED_RED)); 105 | } 106 | 107 | void setup() 108 | { 109 | Serial.begin(115200); 110 | while (!Serial); 111 | 112 | // configure pin in output mode 113 | pinMode(LED_BUILTIN, OUTPUT); 114 | pinMode(LED_BLUE, OUTPUT); 115 | pinMode(LED_RED, OUTPUT); 116 | 117 | delay(100); 118 | 119 | Serial.print(F("\nStarting TimerInterruptLEDDemo on ")); Serial.println(BOARD_NAME); 120 | Serial.println(PORTENTA_H7_TIMER_INTERRUPT_VERSION); 121 | 122 | // Interval in microsecs 123 | if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler)) 124 | { 125 | Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis()); 126 | } 127 | else 128 | Serial.println(F("Can't set ITimer. Select another freq. or timer")); 129 | 130 | // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary 131 | // You can use up to 16 timer for each ISR_Timer 132 | ISR_Timer.setInterval(TIMER_INTERVAL_0_5S, doingSomething1); 133 | ISR_Timer.setInterval(TIMER_INTERVAL_1S, doingSomething2); 134 | ISR_Timer.setInterval(TIMER_INTERVAL_1_5S, doingSomething3); 135 | } 136 | 137 | void loop() 138 | { 139 | /* Nothing to do all is done by hardware. Even no interrupt required. */ 140 | } 141 | -------------------------------------------------------------------------------- /examples/TimerInterruptTest/TimerInterruptTest.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | TimerInterruptTest.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | /* 16 | Notes: 17 | Special design is necessary to share data between interrupt code and the rest of your program. 18 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 19 | variable can not spontaneously change. Because your function may change variables while your program is using them, 20 | the compiler needs this hint. But volatile alone is often not enough. 21 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 22 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 23 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 24 | or the entire sequence of your code which accesses the data. 25 | */ 26 | 27 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 28 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 29 | #endif 30 | 31 | // These define's must be placed at the beginning before #include "Portenta_H7_TimerInterrupt.h" 32 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 33 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 34 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 35 | 36 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 37 | #include "Portenta_H7_TimerInterrupt.h" 38 | 39 | #define LED_OFF HIGH 40 | #define LED_ON LOW 41 | 42 | #ifndef LED_BUILTIN 43 | #define LED_BUILTIN 24 //LEDG // Pin 24 control on-board LED_GREEN on Portenta_H7 44 | #endif 45 | 46 | #ifndef LED_BLUE 47 | #define LED_BLUE 25 //LEDB // Pin 25 control on-board LED_BLUE on Portenta_H7 48 | #endif 49 | 50 | #ifndef LED_RED 51 | #define LED_RED 23 // LEDR // Pin 23 control on-board LED_RED on Portenta_H7 52 | #endif 53 | 54 | unsigned int SWPin = D5; 55 | 56 | // In Portenta_H7, avoid doing something fancy in ISR, for example Serial.print 57 | // Or you can get this run-time error / crash 58 | 59 | void TimerHandler0() 60 | { 61 | static bool toggle0 = false; 62 | 63 | //timer interrupt toggles pin LED_BUILTIN 64 | digitalWrite(LED_BUILTIN, toggle0); 65 | toggle0 = !toggle0; 66 | } 67 | 68 | void TimerHandler1() 69 | { 70 | static bool toggle1 = false; 71 | 72 | //timer interrupt toggles outputPin 73 | digitalWrite(LED_BLUE, toggle1); 74 | digitalWrite(SWPin, toggle1); 75 | toggle1 = !toggle1; 76 | } 77 | 78 | #define TIMER0_INTERVAL_MS 1000 79 | #define TIMER0_DURATION_MS 10000 80 | 81 | #define TIMER1_INTERVAL_MS 3000 82 | #define TIMER1_DURATION_MS 30000 83 | 84 | // Depending on the board, you can select STM32H7 Hardware Timer from TIM1-TIM22 85 | // If you select a Timer not correctly, you'll get a message from compiler 86 | // 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? 87 | 88 | // Portenta_H7 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 89 | // Portenta_H7 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 90 | // Portenta_H7 No timer : TIM9, TIM10, TIM11. Only for STM32F2, STM32F4 and STM32L1 91 | // Portenta_H7 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 92 | 93 | // Init timer TIM15 94 | Portenta_H7_Timer ITimer0(TIM15); 95 | // Init timer TIM16 96 | Portenta_H7_Timer ITimer1(TIM16); 97 | 98 | void setup() 99 | { 100 | Serial.begin(115200); 101 | while (!Serial); 102 | 103 | pinMode(LED_BUILTIN, OUTPUT); 104 | pinMode(LED_BLUE, OUTPUT); 105 | pinMode(SWPin, OUTPUT); 106 | 107 | digitalWrite(LED_BUILTIN, LED_OFF); 108 | digitalWrite(LED_BLUE, LED_OFF); 109 | digitalWrite(SWPin, LOW); 110 | 111 | delay(100); 112 | 113 | Serial.print(F("\nStarting TimerInterruptTest on ")); Serial.println(BOARD_NAME); 114 | Serial.println(PORTENTA_H7_TIMER_INTERRUPT_VERSION); 115 | 116 | // Interval in microsecs 117 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 118 | { 119 | Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis()); 120 | } 121 | else 122 | Serial.println(F("Can't set ITimer0. Select another freq. or timer")); 123 | 124 | // Interval in microsecs 125 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 126 | { 127 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 128 | } 129 | else 130 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 131 | } 132 | 133 | void loop() 134 | { 135 | static unsigned long lastTimer0 = 0; 136 | static unsigned long lastTimer1 = 0; 137 | 138 | static bool timer0Stopped = false; 139 | static bool timer1Stopped = false; 140 | 141 | if (millis() - lastTimer0 > TIMER0_DURATION_MS) 142 | { 143 | lastTimer0 = millis(); 144 | 145 | if (timer0Stopped) 146 | { 147 | Serial.print(F("Start ITimer0, millis() = ")); Serial.println(millis()); 148 | ITimer0.restartTimer(); 149 | } 150 | else 151 | { 152 | Serial.print(F("Stop ITimer0, millis() = ")); Serial.println(millis()); 153 | ITimer0.stopTimer(); 154 | } 155 | timer0Stopped = !timer0Stopped; 156 | } 157 | 158 | if (millis() - lastTimer1 > TIMER1_DURATION_MS) 159 | { 160 | lastTimer1 = millis(); 161 | 162 | if (timer1Stopped) 163 | { 164 | Serial.print(F("Start ITimer1, millis() = ")); Serial.println(millis()); 165 | ITimer1.restartTimer(); 166 | } 167 | else 168 | { 169 | Serial.print(F("Stop ITimer1, millis() = ")); Serial.println(millis()); 170 | ITimer1.stopTimer(); 171 | } 172 | 173 | timer1Stopped = !timer1Stopped; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.cpp 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one SAMD timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | 16 | // To demo how to include files in multi-file Projects 17 | 18 | #include "multiFileProject.h" 19 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.h 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one SAMD timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | 16 | // To demo how to include files in multi-file Projects 17 | 18 | #pragma once 19 | 20 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 21 | //#include "Portenta_H7_TimerInterrupt.h" 22 | 23 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 24 | #include "Portenta_H7_ISR_Timer.hpp" 25 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.ino 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one NRF52 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | *****************************************************************************************************************************/ 15 | 16 | // To demo how to include files in multi-file Projects 17 | 18 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 19 | #error This code is designed to run on Portenta_H7 platform! Please check your Tools->Board setting. 20 | #endif 21 | 22 | #include "multiFileProject.h" 23 | 24 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 25 | #include "Portenta_H7_TimerInterrupt.h" 26 | 27 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 28 | #include "Portenta_H7_ISR_Timer.h" 29 | 30 | void setup() 31 | { 32 | // put your setup code here, to run once: 33 | } 34 | 35 | void loop() 36 | { 37 | // put your main code here, to run repeatedly: 38 | } 39 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Datatypes (KEYWORD1) 3 | ####################################### 4 | 5 | Portenta_H7_TimerInterrupt KEYWORD1 6 | Portenta_H7_Timer KEYWORD1 7 | Portenta_H7_ISRTimer KEYWORD1 8 | Portenta_H7_ISR_Timer KEYWORD1 9 | timerCallback KEYWORD1 10 | timerCallback_p KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | ################################### 17 | # Class Portenta_H7_TimerInterrupt 18 | ################################### 19 | 20 | setFrequency KEYWORD2 21 | setInterval KEYWORD2 22 | attachInterrupt KEYWORD2 23 | attachInterruptInterval KEYWORD2 24 | detachInterrupt KEYWORD2 25 | disableTimer KEYWORD2 26 | reattachInterrupt KEYWORD2 27 | enableTimer KEYWORD2 28 | stopTimer KEYWORD2 29 | restartTimer KEYWORD2 30 | 31 | ############################## 32 | # Class Portenta_H7_ISR_Timer 33 | ############################## 34 | 35 | init KEYWORD2 36 | run KEYWORD2 37 | setTimeout KEYWORD2 38 | setTimer KEYWORD2 39 | changeInterval KEYWORD2 40 | deleteTimer KEYWORD2 41 | restartTimer KEYWORD2 42 | isEnabled KEYWORD2 43 | enable KEYWORD2 44 | disable KEYWORD2 45 | enableAll KEYWORD2 46 | disableAll KEYWORD2 47 | toggle KEYWORD2 48 | getNumTimers KEYWORD2 49 | getNumAvailableTimers KEYWORD2 50 | 51 | ####################################### 52 | # Constants (LITERAL1) 53 | ####################################### 54 | 55 | PORTENTA_H7_TIMER_INTERRUPT_VERSION LITERAL1 56 | PORTENTA_H7_TIMER_INTERRUPT_VERSION_MAJOR LITERAL1 57 | PORTENTA_H7_TIMER_INTERRUPT_VERSION_MINOR LITERAL1 58 | PORTENTA_H7_TIMER_INTERRUPT_VERSION_PATCH LITERAL1 59 | PORTENTA_H7_TIMER_INTERRUPT_VERSION_INT LITERAL1 60 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Portenta_H7_TimerInterrupt", 3 | "version": "1.4.0", 4 | "keywords": "timing, device, control, timer, pwm, interrupt, isr, isr-based, hardware-timer, mission-critical, accuracy, non-blocking, mbed, mbed-portenta, portenta-h7, portentah7, portenta-h7-m7, portenta-h7-m4, portentah7-m7, portentah7-m4, stm32h7, stm32, precise, hardware", 5 | "description": "This library enables you to use Interrupt from Hardware Timers on an STM32H7-based Portenta_H7 board. It now supports 16 ISR-based timers, while consuming only 1 Hardware Timer. Timers' interval is very long (ulong millisecs). The most important feature is they're ISR-based timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy. PWM feature can now be used", 6 | "authors": 7 | { 8 | "name": "Khoi Hoang", 9 | "url": "https://github.com/khoih-prog", 10 | "maintainer": true 11 | }, 12 | "repository": 13 | { 14 | "type": "git", 15 | "url": "https://github.com/khoih-prog/Portenta_H7_TimerInterrupt" 16 | }, 17 | "homepage": "https://github.com/khoih-prog/Portenta_H7_TimerInterrupt", 18 | "export": { 19 | "exclude": [ 20 | "linux", 21 | "extras", 22 | "tests" 23 | ] 24 | }, 25 | "license": "MIT", 26 | "frameworks": "*", 27 | "platforms": "mbed_portenta", 28 | "examples": "examples/*/*/*.ino", 29 | "headers": ["Portenta_H7_TimerInterrupt.h", "Portenta_H7_ISR_Timer.h", "Portenta_H7_ISR_Timer.hpp"] 30 | } 31 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Portenta_H7_TimerInterrupt 2 | version=1.4.0 3 | author=Khoi Hoang 4 | maintainer=Khoi Hoang 5 | sentence=This library enables you to use Interrupt from Hardware Timers on an STM32H7-based Portenta_H7 board. PWM feature can now be used 6 | paragraph=These Portenta_H7 Hardware Timers, using Interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's mandatory if you need to measure some data requiring better accuracy. It now supports 16 ISR-based Timers, while consuming only 1 Hardware Timer. Timers interval is very long (ulong millisecs). The most important feature is they're ISR-based Timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. 7 | category=Device Control 8 | url=https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 9 | architectures=mbed,mbed_portenta,ArduinoCore-mbed 10 | repository=https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 11 | license=MIT 12 | includes=Portenta_H7_TimerInterrupt.h,Portenta_H7_ISR_Timer.h,Portenta_H7_ISR_Timer.hpp 13 | -------------------------------------------------------------------------------- /platformio/platformio.ini: -------------------------------------------------------------------------------- 1 | ;PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | ; ============================================================ 13 | ; chose environment: 14 | ; ESP8266 15 | ; ESP32 16 | ; SAMD 17 | ; NRF52 18 | ; STM32 19 | ; pico 20 | ; ============================================================ 21 | ;default_envs = ESP8266 22 | ;default_envs = ESP32 23 | ;default_envs = SAMD 24 | ;default_envs = pico 25 | ;default_envs = NRF52 26 | ;default_envs = STM32 27 | default_envs = portenta_h7_m7 28 | ;default_envs = portenta_h7_m4 29 | 30 | [env] 31 | ; ============================================================ 32 | ; Serial configuration 33 | ; choose upload speed, serial-monitor speed 34 | ; ============================================================ 35 | upload_speed = 921600 36 | ;upload_port = COM11 37 | ;monitor_speed = 9600 38 | ;monitor_port = COM11 39 | 40 | ; Checks for the compatibility with frameworks and dev/platforms 41 | lib_compat_mode = strict 42 | lib_ldf_mode = chain+ 43 | ;lib_ldf_mode = deep+ 44 | 45 | lib_deps = 46 | 47 | 48 | build_flags = 49 | ; set your debug output (default=Serial) 50 | ; -D DEBUG_ESP_PORT=Serial 51 | ; comment the following line to enable WiFi debugging 52 | ; -D NDEBUG 53 | 54 | [env:portenta_h7_m7] 55 | platform = ststm32 56 | board = portenta_h7_m7 57 | framework = arduino 58 | 59 | [env:portenta_h7_m4] 60 | platform = ststm32 61 | board = portenta_h7_m4 62 | framework = arduino 63 | 64 | [env:pico] 65 | ; ============================================================ 66 | ; Just a sample 67 | ; You have to research and fix if there is issue 68 | ; ============================================================ 69 | platform = raspberrypi 70 | board = pico 71 | framework = arduino 72 | upload_protocol = picotool 73 | 74 | [env:ESP8266] 75 | platform = espressif8266 76 | framework = arduino 77 | ; ============================================================ 78 | ; Board configuration 79 | ; choose your board by uncommenting one of the following lines 80 | ; ============================================================ 81 | ;board = gen4iod 82 | ;board = huzzah 83 | ;board = oak 84 | ;board = esp_wroom_02 85 | ;board = espduino 86 | ;board = espectro 87 | ;board = espino 88 | ;board = espresso_lite_v1 89 | ;board = espresso_lite_v2 90 | ;board = esp12e 91 | ;board = esp01_1m 92 | ;board = esp01 93 | ;board = esp07 94 | ;board = esp8285 95 | ;board = heltec_wifi_kit_8 96 | ;board = inventone 97 | ;board = nodemcu 98 | board = nodemcuv2 99 | ;board = modwifi 100 | ;board = phoenix_v1 101 | ;board = phoenix_v2 102 | ;board = sparkfunBlynk 103 | ;board = thing 104 | ;board = thingdev 105 | ;board = esp210 106 | ;board = espinotee 107 | ;board = d1 108 | ;board = d1_mini 109 | ;board = d1_mini_lite 110 | ;board = d1_mini_pro 111 | ;board = wifi_slot 112 | ;board = wifiduino 113 | ;board = wifinfo 114 | ;board = wio_link 115 | ;board = wio_node 116 | ;board = xinabox_cw01 117 | ;board = esp32doit-devkit-v1 118 | 119 | [env:ESP32] 120 | platform = espressif32 121 | framework = arduino 122 | ; ============================================================ 123 | ; Board configuration 124 | ; choose your board by uncommenting one of the following lines 125 | ; ============================================================ 126 | ;board = esp32cam 127 | ;board = alksesp32 128 | ;board = featheresp32 129 | ;board = espea32 130 | ;board = bpi-bit 131 | ;board = d-duino-32 132 | board = esp32doit-devkit-v1 133 | ;board = pocket_32 134 | ;board = fm-devkit 135 | ;board = pico32 136 | ;board = esp32-evb 137 | ;board = esp32-gateway 138 | ;board = esp32-pro 139 | ;board = esp32-poe 140 | ;board = oroca_edubot 141 | ;board = onehorse32dev 142 | ;board = lopy 143 | ;board = lopy4 144 | ;board = wesp32 145 | ;board = esp32thing 146 | ;board = sparkfun_lora_gateway_1-channel 147 | ;board = ttgo-lora32-v1 148 | ;board = ttgo-t-beam 149 | ;board = turta_iot_node 150 | ;board = lolin_d32 151 | ;board = lolin_d32_pro 152 | ;board = lolin32 153 | ;board = wemosbat 154 | ;board = widora-air 155 | ;board = xinabox_cw02 156 | ;board = iotbusio 157 | ;board = iotbusproteus 158 | ;board = nina_w10 159 | 160 | [env:SAMD] 161 | platform = atmelsam 162 | framework = arduino 163 | ; ============================================================ 164 | ; Choose your board by uncommenting one of the following lines 165 | ; ============================================================ 166 | ; ============================================================ 167 | ; Board configuration Adafruit SAMD 168 | ; ============================================================ 169 | 170 | ;board = adafruit_feather_m0 171 | ;board = adafruit_feather_m0_express 172 | ;board = adafruit_metro_m0 173 | ;board = adafruit_circuitplayground_m0 174 | ;board = adafruit_gemma_m0 175 | ;board = adafruit_trinket_m0 176 | ;board = adafruit_itsybitsy_m0 177 | ;board = adafruit_pirkey 178 | ;board = adafruit_hallowing 179 | ;board = adafruit_crickit_m0 180 | ;board = adafruit_metro_m4 181 | ;board = adafruit_grandcentral_m4 182 | board = adafruit_itsybitsy_m4 183 | ;board = adafruit_feather_m4 184 | ;board = adafruit_trellis_m4 185 | ;board = adafruit_pyportal_m4 186 | ;board = adafruit_pyportal_m4_titano 187 | ;board = adafruit_pybadge_m4 188 | ;board = adafruit_metro_m4_airliftlite 189 | ;board = adafruit_pygamer_m4 190 | ;board = adafruit_pygamer_advance_m4 191 | ;board = adafruit_pybadge_airlift_m4 192 | ;board = adafruit_monster_m4sk 193 | ;board = adafruit_hallowing_m4 194 | 195 | ; ============================================================ 196 | ; Board configuration Arduino SAMD and SAM 197 | ; ============================================================ 198 | 199 | ;board = arduino_zero_edbg 200 | ;board = arduino_zero_native 201 | ;board = mkr1000 202 | ;board = mkrzero 203 | ;board = mkrwifi1010 204 | ;board = nano_33_iot 205 | ;board = mkrfox1200 206 | ;board = mkrwan1300 207 | ;board = mkrwan1310 208 | ;board = mkrgsm1400 209 | ;board = mkrnb1500 210 | ;board = mkrvidor4000 211 | ;board = adafruit_circuitplayground_m0 212 | ;board = mzero_pro_bl_dbg 213 | ;board = mzero_pro_bl 214 | ;board = mzero_bl 215 | ;board = tian 216 | ;board = tian_cons 217 | ;board = arduino_due_x_dbg 218 | ;board = arduino_due_x 219 | 220 | ; ============================================================ 221 | ; Board configuration Seeeduino SAMD 222 | ; ============================================================ 223 | 224 | ;board = seeed_wio_terminal 225 | ;board = Seeed_femto_m0 226 | ;board = seeed_XIAO_m0 227 | ;board = Wio_Lite_MG126 228 | ;board = WioGPS 229 | ;board = zero 230 | ;board = rolawan 231 | ;board = seeed_grove_ui_wireless 232 | 233 | 234 | [env:NRF52] 235 | platform = nordicnrf52 236 | framework = arduino 237 | ; ============================================================ 238 | ; Board configuration Adafruit nRF52 239 | ; choose your board by uncommenting one of the following lines 240 | ; ============================================================ 241 | ;board = feather52832 242 | board = feather52840 243 | ;board = feather52840sense 244 | ;board = itsybitsy52840 245 | ;board = cplaynrf52840 246 | ;board = cluenrf52840 247 | ;board = metro52840 248 | ;board = pca10056 249 | ;board = particle_xenon 250 | ;board = mdbt50qrx 251 | ;board = ninab302 252 | ;board = ninab112 253 | 254 | [env:STM32] 255 | platform = ststm32 256 | framework = arduino 257 | 258 | ; ============================================================ 259 | ; Choose your board by uncommenting one of the following lines 260 | ; ============================================================ 261 | 262 | ; ============================================================ 263 | ; Board configuration Nucleo-144 264 | ; ============================================================ 265 | 266 | ;board = nucleo_f207zg 267 | ;board = nucleo_f429zi 268 | ;board = nucleo_f746zg 269 | ;board = nucleo_f756zg 270 | ;board = nucleo_f767zi 271 | ;board = nucleo_h743zi 272 | ;board = nucleo_l496zg 273 | ;board = nucleo_l496zg-p 274 | ;board = nucleo_l4r5zi 275 | ;board = nucleo_l4r5zi-p 276 | 277 | ; ============================================================ 278 | ; Board configuration Nucleo-64 279 | ; ============================================================ 280 | 281 | ;board = nucleo_f030r8 282 | ;board = nucleo_f072rb 283 | 284 | ;board = nucleo_f091rc 285 | ;board = nucleo_f103rb 286 | ;board = nucleo_f302r8 287 | ;board = nucleo_f303re 288 | ;board = nucleo_f401re 289 | ;board = nucleo_f411re 290 | ;board = nucleo_f446re 291 | ;board = nucleo_g071rb 292 | ;board = nucleo_g431rb 293 | ;board = nucleo_g474re 294 | ;board = nucleo_l053r8 295 | ;board = nucleo_l073rz 296 | ;board = nucleo_l152re 297 | ;board = nucleo_l433rc_p 298 | ;board = nucleo_l452re 299 | ;board = nucleo_l452re-p 300 | ;board = nucleo_l476rg 301 | ;board = pnucleo_wb55rg 302 | 303 | ; ============================================================ 304 | ; Board configuration Nucleo-32 305 | ; ============================================================ 306 | 307 | ;board = nucleo_f031k6 308 | ;board = nucleo_l031k6 309 | ;board = nucleo_l412kb 310 | ;board = nucleo_l432lc 311 | ;board = nucleo_f303k8 312 | ;board = nucleo_g431kb 313 | 314 | ; ============================================================ 315 | ; Board configuration Discovery Boards 316 | ; ============================================================ 317 | 318 | ;board = disco_f030r8 319 | ;board = disco_f072rb 320 | ;board = disco_f030r8 321 | ;board = disco_f100rb 322 | ;board = disco_f407vg 323 | ;board = disco_f413zh 324 | ;board = disco_f746ng 325 | ;board = disco_g0316 326 | ;board = disco_l475vg_iot 327 | ;board = disco_f072cz-lrwan1 328 | 329 | ; ============================================================ 330 | ; Board configuration STM32MP1 Boards 331 | ; ============================================================ 332 | 333 | ;board = stm32mp157a-dk1 334 | ;board = stm32mp157c-dk2 335 | 336 | ; ============================================================ 337 | ; Board configuration Generic Boards 338 | ; ============================================================ 339 | 340 | ;board = bluepill_f103c6 341 | ;board = bluepill_f103c8 342 | ;board = blackpill_f103c8 343 | ;board = stm32f103cx 344 | ;board = stm32f103rx 345 | ;board = stm32f103tx 346 | ;board = stm32f103vx 347 | ;board = stm32f103zx 348 | ;board = stm32f103zet6 349 | ;board = maplemini_f103cb 350 | ;board = blackpill_f303cc 351 | ;board = black_f407ve 352 | ;board = black_f407vg 353 | ;board = black_f407ze 354 | ;board = black_f407zg 355 | ;board = blue_f407ve_mini 356 | ;board = blackpill_f401cc 357 | ;board = blackpill_f411ce 358 | ;board = coreboard_f401rc 359 | ;board = feather_f405 360 | 361 | ; ============================================================ 362 | ; Board configuration Many more Boards to be filled 363 | ; ============================================================ 364 | 365 | -------------------------------------------------------------------------------- /src/Portenta_H7_ISR_Timer-Impl.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Portenta_H7_ISR_Timer-Impl.h 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | 15 | Version: 1.4.0 16 | 17 | Version Modified By Date Comments 18 | ------- ----------- ---------- ----------- 19 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 20 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 21 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 22 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 23 | *****************************************************************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #ifndef ISR_TIMER_GENERIC_IMPL_H 28 | #define ISR_TIMER_GENERIC_IMPL_H 29 | 30 | //#include "Portenta_H7_ISR_Timer.h" 31 | #include 32 | 33 | Portenta_H7_ISR_Timer::Portenta_H7_ISR_Timer() 34 | : numTimers (-1) 35 | { 36 | } 37 | 38 | void Portenta_H7_ISR_Timer::init() 39 | { 40 | unsigned long current_millis = millis(); //elapsed(); 41 | 42 | for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) 43 | { 44 | memset((void*) &timer[i], 0, sizeof (timer_t)); 45 | timer[i].prev_millis = current_millis; 46 | } 47 | 48 | numTimers = 0; 49 | } 50 | 51 | void Portenta_H7_ISR_Timer::run() 52 | { 53 | uint8_t i; 54 | unsigned long current_millis; 55 | 56 | // get current time 57 | current_millis = millis(); //elapsed(); 58 | 59 | for (i = 0; i < MAX_NUMBER_TIMERS; i++) 60 | { 61 | 62 | timer[i].toBeCalled = TIMER_DEFCALL_DONTRUN; 63 | 64 | // no callback == no timer, i.e. jump over empty slots 65 | if (timer[i].callback != NULL) 66 | { 67 | 68 | // is it time to process this timer ? 69 | // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592 70 | 71 | if ((current_millis - timer[i].prev_millis) >= timer[i].delay) 72 | { 73 | unsigned long skipTimes = (current_millis - timer[i].prev_millis) / timer[i].delay; 74 | 75 | // update time 76 | timer[i].prev_millis += timer[i].delay * skipTimes; 77 | 78 | // check if the timer callback has to be executed 79 | if (timer[i].enabled) 80 | { 81 | 82 | // "run forever" timers must always be executed 83 | if (timer[i].maxNumRuns == TIMER_RUN_FOREVER) 84 | { 85 | timer[i].toBeCalled = TIMER_DEFCALL_RUNONLY; 86 | } 87 | // other timers get executed the specified number of times 88 | else if (timer[i].numRuns < timer[i].maxNumRuns) 89 | { 90 | timer[i].toBeCalled = TIMER_DEFCALL_RUNONLY; 91 | timer[i].numRuns++; 92 | 93 | // after the last run, delete the timer 94 | if (timer[i].numRuns >= timer[i].maxNumRuns) 95 | { 96 | timer[i].toBeCalled = TIMER_DEFCALL_RUNANDDEL; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | for (i = 0; i < MAX_NUMBER_TIMERS; i++) 105 | { 106 | if (timer[i].toBeCalled == TIMER_DEFCALL_DONTRUN) 107 | continue; 108 | 109 | if (timer[i].hasParam) 110 | (*(timerCallback_p)timer[i].callback)(timer[i].param); 111 | else 112 | (*(timerCallback)timer[i].callback)(); 113 | 114 | if (timer[i].toBeCalled == TIMER_DEFCALL_RUNANDDEL) 115 | deleteTimer(i); 116 | } 117 | } 118 | 119 | 120 | // find the first available slot 121 | // return -1 if none found 122 | int Portenta_H7_ISR_Timer::findFirstFreeSlot() 123 | { 124 | // all slots are used 125 | if (numTimers >= MAX_NUMBER_TIMERS) 126 | { 127 | return -1; 128 | } 129 | 130 | // return the first slot with no callback (i.e. free) 131 | for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) 132 | { 133 | if (timer[i].callback == NULL) 134 | { 135 | return i; 136 | } 137 | } 138 | 139 | // no free slots found 140 | return -1; 141 | } 142 | 143 | 144 | int Portenta_H7_ISR_Timer::setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n) 145 | { 146 | int freeTimer; 147 | 148 | if (numTimers < 0) 149 | { 150 | init(); 151 | } 152 | 153 | freeTimer = findFirstFreeSlot(); 154 | 155 | if (freeTimer < 0) 156 | { 157 | return -1; 158 | } 159 | 160 | if (f == NULL) 161 | { 162 | return -1; 163 | } 164 | 165 | timer[freeTimer].delay = d; 166 | timer[freeTimer].callback = f; 167 | timer[freeTimer].param = p; 168 | timer[freeTimer].hasParam = h; 169 | timer[freeTimer].maxNumRuns = n; 170 | timer[freeTimer].enabled = true; 171 | timer[freeTimer].prev_millis = millis(); 172 | 173 | numTimers++; 174 | 175 | return freeTimer; 176 | } 177 | 178 | 179 | int Portenta_H7_ISR_Timer::setTimer(unsigned long d, timerCallback f, unsigned n) 180 | { 181 | return setupTimer(d, (void *)f, NULL, false, n); 182 | } 183 | 184 | int Portenta_H7_ISR_Timer::setTimer(unsigned long d, timerCallback_p f, void* p, unsigned n) 185 | { 186 | return setupTimer(d, (void *)f, p, true, n); 187 | } 188 | 189 | int Portenta_H7_ISR_Timer::setInterval(unsigned long d, timerCallback f) 190 | { 191 | return setupTimer(d, (void *)f, NULL, false, TIMER_RUN_FOREVER); 192 | } 193 | 194 | int Portenta_H7_ISR_Timer::setInterval(unsigned long d, timerCallback_p f, void* p) 195 | { 196 | return setupTimer(d, (void *)f, p, true, TIMER_RUN_FOREVER); 197 | } 198 | 199 | int Portenta_H7_ISR_Timer::setTimeout(unsigned long d, timerCallback f) 200 | { 201 | return setupTimer(d, (void *)f, NULL, false, TIMER_RUN_ONCE); 202 | } 203 | 204 | int Portenta_H7_ISR_Timer::setTimeout(unsigned long d, timerCallback_p f, void* p) 205 | { 206 | return setupTimer(d, (void *)f, p, true, TIMER_RUN_ONCE); 207 | } 208 | 209 | bool Portenta_H7_ISR_Timer::changeInterval(unsigned numTimer, unsigned long d) 210 | { 211 | if (numTimer >= MAX_NUMBER_TIMERS) 212 | { 213 | return false; 214 | } 215 | 216 | // Updates interval of existing specified timer 217 | if (timer[numTimer].callback != NULL) 218 | { 219 | timer[numTimer].delay = d; 220 | timer[numTimer].prev_millis = millis(); 221 | 222 | return true; 223 | } 224 | 225 | // false return for non-used numTimer, no callback 226 | return false; 227 | } 228 | 229 | void Portenta_H7_ISR_Timer::deleteTimer(unsigned timerId) 230 | { 231 | if (timerId >= MAX_NUMBER_TIMERS) 232 | { 233 | return; 234 | } 235 | 236 | // nothing to delete if no timers are in use 237 | if (numTimers == 0) 238 | { 239 | return; 240 | } 241 | 242 | // don't decrease the number of timers if the specified slot is already empty 243 | if (timer[timerId].callback != NULL) 244 | { 245 | memset((void*) &timer[timerId], 0, sizeof (timer_t)); 246 | timer[timerId].prev_millis = millis(); 247 | 248 | // update number of timers 249 | numTimers--; 250 | } 251 | } 252 | 253 | // function contributed by code@rowansimms.com 254 | void Portenta_H7_ISR_Timer::restartTimer(unsigned numTimer) 255 | { 256 | if (numTimer >= MAX_NUMBER_TIMERS) 257 | { 258 | return; 259 | } 260 | 261 | timer[numTimer].prev_millis = millis(); 262 | } 263 | 264 | 265 | bool Portenta_H7_ISR_Timer::isEnabled(unsigned numTimer) 266 | { 267 | if (numTimer >= MAX_NUMBER_TIMERS) 268 | { 269 | return false; 270 | } 271 | 272 | return timer[numTimer].enabled; 273 | } 274 | 275 | 276 | void Portenta_H7_ISR_Timer::enable(unsigned numTimer) 277 | { 278 | if (numTimer >= MAX_NUMBER_TIMERS) 279 | { 280 | return; 281 | } 282 | 283 | timer[numTimer].enabled = true; 284 | } 285 | 286 | 287 | void Portenta_H7_ISR_Timer::disable(unsigned numTimer) 288 | { 289 | if (numTimer >= MAX_NUMBER_TIMERS) 290 | { 291 | return; 292 | } 293 | 294 | timer[numTimer].enabled = false; 295 | } 296 | 297 | void Portenta_H7_ISR_Timer::enableAll() 298 | { 299 | // Enable all timers with a callback assigned (used) 300 | 301 | for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) 302 | { 303 | if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) 304 | { 305 | timer[i].enabled = true; 306 | } 307 | } 308 | } 309 | 310 | void Portenta_H7_ISR_Timer::disableAll() 311 | { 312 | // Disable all timers with a callback assigned (used) 313 | 314 | for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) 315 | { 316 | if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) 317 | { 318 | timer[i].enabled = false; 319 | } 320 | } 321 | } 322 | 323 | void Portenta_H7_ISR_Timer::toggle(unsigned numTimer) 324 | { 325 | if (numTimer >= MAX_NUMBER_TIMERS) 326 | { 327 | return; 328 | } 329 | 330 | timer[numTimer].enabled = !timer[numTimer].enabled; 331 | } 332 | 333 | 334 | unsigned Portenta_H7_ISR_Timer::getNumTimers() 335 | { 336 | return numTimers; 337 | } 338 | 339 | #endif // ISR_TIMER_GENERIC_IMPL_H 340 | -------------------------------------------------------------------------------- /src/Portenta_H7_ISR_Timer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Portenta_H7_ISR_Timer.h 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and a1void conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | 15 | Version: 1.4.0 16 | 17 | Version Modified By Date Comments 18 | ------- ----------- ---------- ----------- 19 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 20 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 21 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 22 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 23 | *****************************************************************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #ifndef ISR_TIMER_GENERIC_H 28 | #define ISR_TIMER_GENERIC_H 29 | 30 | #include "Portenta_H7_ISR_Timer.hpp" 31 | #include "Portenta_H7_ISR_Timer-Impl.h" 32 | 33 | #endif // ISR_TIMER_GENERIC_H 34 | 35 | -------------------------------------------------------------------------------- /src/Portenta_H7_ISR_Timer.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Portenta_H7_ISR_Timer.hpp 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and a1void conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | 15 | Version: 1.4.0 16 | 17 | Version Modified By Date Comments 18 | ------- ----------- ---------- ----------- 19 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 20 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 21 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 22 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 23 | *****************************************************************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #ifndef ISR_TIMER_GENERIC_HPP 28 | #define ISR_TIMER_GENERIC_HPP 29 | 30 | #if !( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 31 | #error This code is intended to run on the MBED ARDUINO_PORTENTA_H7 platform! Please check your Tools->Board setting. 32 | #endif 33 | 34 | #ifndef PORTENTA_H7_TIMER_INTERRUPT_VERSION 35 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION "Portenta_H7_TimerInterrupt v1.4.0" 36 | 37 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_MAJOR 1 38 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_MINOR 4 39 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_PATCH 0 40 | 41 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_INT 1004000 42 | #endif 43 | 44 | #include "TimerInterrupt_Generic_Debug.h" 45 | 46 | #include 47 | 48 | #include 49 | 50 | #if defined(ARDUINO) 51 | #if ARDUINO >= 100 52 | #include 53 | #else 54 | #include 55 | #endif 56 | #endif 57 | 58 | #define Portenta_H7_ISR_Timer Portenta_H7_ISRTimer 59 | 60 | typedef void (*timerCallback)(); 61 | typedef void (*timerCallback_p)(void *); 62 | 63 | class Portenta_H7_ISR_Timer 64 | { 65 | 66 | public: 67 | // maximum number of timers 68 | #define MAX_NUMBER_TIMERS 16 69 | #define TIMER_RUN_FOREVER 0 70 | #define TIMER_RUN_ONCE 1 71 | 72 | // constructor 73 | Portenta_H7_ISR_Timer(); 74 | 75 | void init(); 76 | 77 | // this function must be called inside loop() 78 | void run(); 79 | 80 | // Timer will call function 'f' every 'd' milliseconds forever 81 | // returns the timer number (numTimer) on success or 82 | // -1 on failure (f == NULL) or no free timers 83 | int setInterval(unsigned long d, timerCallback f); 84 | 85 | // Timer will call function 'f' with parameter 'p' every 'd' milliseconds forever 86 | // returns the timer number (numTimer) on success or 87 | // -1 on failure (f == NULL) or no free timers 88 | int setInterval(unsigned long d, timerCallback_p f, void* p); 89 | 90 | // Timer will call function 'f' after 'd' milliseconds one time 91 | // returns the timer number (numTimer) on success or 92 | // -1 on failure (f == NULL) or no free timers 93 | int setTimeout(unsigned long d, timerCallback f); 94 | 95 | // Timer will call function 'f' with parameter 'p' after 'd' milliseconds one time 96 | // returns the timer number (numTimer) on success or 97 | // -1 on failure (f == NULL) or no free timers 98 | int setTimeout(unsigned long d, timerCallback_p f, void* p); 99 | 100 | // Timer will call function 'f' every 'd' milliseconds 'n' times 101 | // returns the timer number (numTimer) on success or 102 | // -1 on failure (f == NULL) or no free timers 103 | int setTimer(unsigned long d, timerCallback f, unsigned n); 104 | 105 | // Timer will call function 'f' with parameter 'p' every 'd' milliseconds 'n' times 106 | // returns the timer number (numTimer) on success or 107 | // -1 on failure (f == NULL) or no free timers 108 | int setTimer(unsigned long d, timerCallback_p f, void* p, unsigned n); 109 | 110 | // updates interval of the specified timer 111 | bool changeInterval(unsigned numTimer, unsigned long d); 112 | 113 | // destroy the specified timer 114 | void deleteTimer(unsigned numTimer); 115 | 116 | // restart the specified timer 117 | void restartTimer(unsigned numTimer); 118 | 119 | // returns true if the specified timer is enabled 120 | bool isEnabled(unsigned numTimer); 121 | 122 | // enables the specified timer 123 | void enable(unsigned numTimer); 124 | 125 | // disables the specified timer 126 | void disable(unsigned numTimer); 127 | 128 | // enables all timers 129 | void enableAll(); 130 | 131 | // disables all timers 132 | void disableAll(); 133 | 134 | // enables the specified timer if it's currently disabled, and vice-versa 135 | void toggle(unsigned numTimer); 136 | 137 | // returns the number of used timers 138 | unsigned getNumTimers(); 139 | 140 | // returns the number of available timers 141 | unsigned getNumAvailableTimers() 142 | { 143 | return MAX_NUMBER_TIMERS - numTimers; 144 | }; 145 | 146 | private: 147 | // deferred call constants 148 | #define TIMER_DEFCALL_DONTRUN 0 // don't call the callback function 149 | #define TIMER_DEFCALL_RUNONLY 1 // call the callback function but don't delete the timer 150 | #define TIMER_DEFCALL_RUNANDDEL 2 // call the callback function and delete the timer 151 | 152 | // low level function to initialize and enable a new timer 153 | // returns the timer number (numTimer) on success or 154 | // -1 on failure (f == NULL) or no free timers 155 | int setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n); 156 | 157 | // find the first available slot 158 | int findFirstFreeSlot(); 159 | 160 | typedef struct 161 | { 162 | unsigned long prev_millis; // value returned by the millis() function in the previous run() call 163 | void* callback; // pointer to the callback function 164 | void* param; // function parameter 165 | bool hasParam; // true if callback takes a parameter 166 | unsigned long delay; // delay value 167 | unsigned maxNumRuns; // number of runs to be executed 168 | unsigned numRuns; // number of executed runs 169 | bool enabled; // true if enabled 170 | unsigned toBeCalled; // deferred function call (sort of) - N.B.: only used in run() 171 | } timer_t; 172 | 173 | volatile timer_t timer[MAX_NUMBER_TIMERS]; 174 | 175 | // actual number of timers in use (-1 means uninitialized) 176 | volatile int numTimers; 177 | }; 178 | 179 | #endif // ISR_TIMER_GENERIC_HPP 180 | 181 | -------------------------------------------------------------------------------- /src/Portenta_H7_TimerInterrupt.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Portenta_H7_TimerInterrupt.h 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | 15 | Version: 1.4.0 16 | 17 | Version Modified By Date Comments 18 | ------- ----------- ---------- ----------- 19 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 20 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 21 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 22 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 23 | *****************************************************************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #ifndef PORTENTA_H7_TIMERINTERRUPT_H 28 | #define PORTENTA_H7_TIMERINTERRUPT_H 29 | 30 | #if ( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) 31 | #warning Use MBED ARDUINO_PORTENTA_H7 and LittleFS 32 | 33 | #if defined(BOARD_NAME) 34 | #undef BOARD_NAME 35 | #endif 36 | 37 | #if defined(CORE_CM7) 38 | #warning Using Portenta H7 M7 core 39 | #define BOARD_NAME "PORTENTA_H7_M7" 40 | #else 41 | #warning Using Portenta H7 M4 core 42 | #define BOARD_NAME "PORTENTA_H7_M4" 43 | #endif 44 | 45 | #else 46 | #error This code is intended to run on the MBED ARDUINO_PORTENTA_H7 platform! Please check your Tools->Board setting. 47 | #endif 48 | 49 | #ifndef PORTENTA_H7_TIMER_INTERRUPT_VERSION 50 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION "Portenta_H7_TimerInterrupt v1.4.0" 51 | 52 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_MAJOR 1 53 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_MINOR 4 54 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_PATCH 0 55 | 56 | #define PORTENTA_H7_TIMER_INTERRUPT_VERSION_INT 1004000 57 | #endif 58 | 59 | 60 | /////////////////////////////////////////// 61 | 62 | #include "stm32/HardwareTimer.h" 63 | 64 | /////////////////////////////////////////// 65 | 66 | #if defined(ARDUINO) 67 | #if ARDUINO >= 100 68 | #include 69 | #else 70 | #include 71 | #endif 72 | #endif 73 | 74 | #include "TimerInterrupt_Generic_Debug.h" 75 | 76 | class Portenta_H7_TimerInterrupt; 77 | 78 | typedef Portenta_H7_TimerInterrupt Portenta_H7_Timer; 79 | 80 | typedef void (*timerCallback) (); 81 | 82 | 83 | class Portenta_H7_TimerInterrupt 84 | { 85 | private: 86 | TIM_TypeDef* _timer; 87 | HardwareTimer* _hwTimer = NULL; 88 | 89 | timerCallback _callback; // pointer to the callback function 90 | float _frequency; // Timer frequency 91 | uint32_t _timerCount; // count to activate timer 92 | 93 | public: 94 | 95 | Portenta_H7_TimerInterrupt(TIM_TypeDef* timer) 96 | { 97 | _timer = timer; 98 | 99 | _hwTimer = new HardwareTimer(_timer); 100 | 101 | _callback = NULL; 102 | }; 103 | 104 | ~Portenta_H7_TimerInterrupt() 105 | { 106 | if (_hwTimer) 107 | delete _hwTimer; 108 | } 109 | 110 | #define TIM_CLOCK_FREQ ( (float) 1000000.0f ) 111 | 112 | // frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely 113 | // No params and duration now. To be addes in the future by adding similar functions here or to STM32-hal-timer.c 114 | bool setFrequency(float frequency, timerCallback callback) 115 | { 116 | if ( (frequency == 0.0f) || (frequency > 100000.0f) || (callback == NULL) ) 117 | { 118 | TISR_LOGERROR(F("Error. frequency == 0, higher than 100KHz or callback == NULL ")); 119 | 120 | return false; 121 | } 122 | 123 | // select timer frequency is 1MHz for better accuracy. We don't use 16-bit prescaler for now. 124 | // Will use later if very low frequency is needed. 125 | //_frequency = 1000000; 126 | //_timerCount = (uint32_t) _frequency / frequency; 127 | 128 | //TISR_LOGWARN1(F("Portenta_H7_TimerInterrupt: Timer Input Freq (Hz) ="), _hwTimer->getTimerClkFreq()); 129 | //TISR_LOGWARN3(F("Frequency ="), _frequency, F(", _count ="), (uint32_t) (_timerCount)); 130 | 131 | // Hardware timer is preset in RP2040 at 1MHz / 1uS 132 | _frequency = frequency; 133 | _timerCount = (uint32_t) TIM_CLOCK_FREQ / frequency; 134 | 135 | TISR_LOGWARN1(F("Timer Input Freq (Hz) = "), _hwTimer->getTimerClkFreq()); 136 | TISR_LOGWARN3(F("Frequency ="), _frequency, F(", _count = "), (uint32_t) (_timerCount)); 137 | 138 | _hwTimer->setCount(0, MICROSEC_FORMAT); 139 | 140 | _hwTimer->setOverflow(_timerCount, MICROSEC_FORMAT); 141 | ////// 142 | 143 | _hwTimer->attachInterrupt(callback); 144 | _hwTimer->resume(); 145 | 146 | return true; 147 | } 148 | 149 | // interval (in microseconds) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely 150 | // No params and duration now. To be addes in the future by adding similar functions here or to STM32-hal-timer.c 151 | bool setInterval(unsigned long interval, timerCallback callback) 152 | { 153 | return setFrequency((float) (1000000.0f / interval), callback); 154 | } 155 | 156 | bool attachInterrupt(float frequency, timerCallback callback) 157 | { 158 | return setFrequency(frequency, callback); 159 | } 160 | 161 | // interval (in microseconds) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely 162 | // No params and duration now. To be addes in the future by adding similar functions here or to STM32-hal-timer.c 163 | bool attachInterruptInterval(unsigned long interval, timerCallback callback) 164 | { 165 | return setFrequency( (float) ( 1000000.0f / interval), callback); 166 | } 167 | 168 | void detachInterrupt() 169 | { 170 | _hwTimer->detachInterrupt(); 171 | } 172 | 173 | void disableTimer() 174 | { 175 | //_hwTimer->detachInterrupt(); 176 | _hwTimer->pause(); 177 | } 178 | 179 | // Duration (in milliseconds). Duration = 0 or not specified => run indefinitely 180 | void reattachInterrupt() 181 | { 182 | setFrequency(_frequency, _callback); 183 | } 184 | 185 | // Duration (in milliseconds). Duration = 0 or not specified => run indefinitely 186 | void enableTimer() 187 | { 188 | //setFrequency(_frequency, _callback); 189 | _hwTimer->setCount(0, MICROSEC_FORMAT); 190 | _hwTimer->resume(); 191 | } 192 | 193 | // Just stop clock source, clear the count 194 | void stopTimer() 195 | { 196 | _hwTimer->pause(); 197 | _hwTimer->setCount(0, MICROSEC_FORMAT); 198 | } 199 | 200 | // Just reconnect clock source, start current count from 0 201 | void restartTimer() 202 | { 203 | _hwTimer->setCount(0, MICROSEC_FORMAT); 204 | _hwTimer->resume(); 205 | } 206 | }; // class Portenta_H7_TimerInterrupt 207 | 208 | #endif // PORTENTA_H7_TIMERINTERRUPT_H 209 | 210 | -------------------------------------------------------------------------------- /src/TimerInterrupt_Generic_Debug.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | TimerInterrupt_Generic_Debug.h 3 | For Portenta_H7 boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 10 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 11 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 12 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 13 | This important feature is absolutely necessary for mission-critical tasks. 14 | 15 | Version: 1.4.0 16 | 17 | Version Modified By Date Comments 18 | ------- ----------- ---------- ----------- 19 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 20 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 21 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 22 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 23 | *****************************************************************************************************************************/ 24 | 25 | #pragma once 26 | 27 | #ifndef TIMERINTERRUPT_GENERIC_DEBUG_H 28 | #define TIMERINTERRUPT_GENERIC_DEBUG_H 29 | 30 | #ifdef TIMERINTERRUPT_DEBUG_PORT 31 | #define TISR_DBG_PORT TIMERINTERRUPT_DEBUG_PORT 32 | #else 33 | #define TISR_DBG_PORT Serial 34 | #endif 35 | 36 | // Change _TIMERINTERRUPT_LOGLEVEL_ to set tracing and logging verbosity 37 | // 0: DISABLED: no logging 38 | // 1: ERROR: errors 39 | // 2: WARN: errors and warnings 40 | // 3: INFO: errors, warnings and informational (default) 41 | // 4: DEBUG: errors, warnings, informational and debug 42 | 43 | #ifndef _TIMERINTERRUPT_LOGLEVEL_ 44 | #define _TIMERINTERRUPT_LOGLEVEL_ 1 45 | #endif 46 | 47 | ////////////////////////////////////////// 48 | 49 | const char TISR_MARK[] = "[TISR] "; 50 | const char TISR_SP[] = " "; 51 | 52 | #define TISR_PRINT TISR_DBG_PORT.print 53 | #define TISR_PRINTLN TISR_DBG_PORT.println 54 | 55 | #define TISR_PRINT_MARK TISR_PRINT(TISR_MARK) 56 | #define TISR_PRINT_SP TISR_PRINT(TISR_SP) 57 | 58 | /////////////////////////////////////// 59 | 60 | #define TISR_LOGERROR(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 61 | #define TISR_LOGERROR0(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT(x); } 62 | #define TISR_LOGERROR1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 63 | #define TISR_LOGERROR2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 64 | #define TISR_LOGERROR3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINTLN(w); } 65 | #define TISR_LOGERROR5(x,y,z,w, xx, yy) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINT(w); TISR_PRINT(xx); TISR_PRINTLN(yy); } 66 | 67 | /////////////////////////////////////// 68 | 69 | #define TISR_LOGWARN(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 70 | #define TISR_LOGWARN0(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT(x); } 71 | #define TISR_LOGWARN1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 72 | #define TISR_LOGWARN2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 73 | #define TISR_LOGWARN3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINTLN(w); } 74 | #define TISR_LOGWARN5(x,y,z,w, xx, yy) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINT(w); TISR_PRINT(xx); TISR_PRINTLN(yy); } 75 | 76 | /////////////////////////////////////// 77 | 78 | #define TISR_LOGINFO(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 79 | #define TISR_LOGINFO0(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT(x); } 80 | #define TISR_LOGINFO1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 81 | #define TISR_LOGINFO2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 82 | #define TISR_LOGINFO3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINTLN(w); } 83 | #define TISR_LOGINFO5(x,y,z,w, xx, yy) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINT(w); TISR_PRINT(xx); TISR_PRINTLN(yy); } 84 | 85 | /////////////////////////////////////// 86 | 87 | #define TISR_LOGDEBUG(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 88 | #define TISR_LOGDEBUG0(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT(x); } 89 | #define TISR_LOGDEBUG1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 90 | #define TISR_LOGDEBUG2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 91 | #define TISR_LOGDEBUG3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINTLN(w); } 92 | #define TISR_LOGDEBUG5(x,y,z,w, xx, yy) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINT(z); TISR_PRINT(w); TISR_PRINT(xx); TISR_PRINTLN(yy); } 93 | 94 | /////////////////////////////////////// 95 | 96 | #endif //TIMERINTERRUPT_GENERIC_DEBUG_H 97 | -------------------------------------------------------------------------------- /src/stm32/HardwareTimer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | HardwareTimer.h 3 | 4 | For Portenta_H7 boards 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 11 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 12 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 13 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 14 | This important feature is absolutely necessary for mission-critical tasks. 15 | 16 | Version: 1.4.0 17 | 18 | Version Modified By Date Comments 19 | ------- ----------- ---------- ----------- 20 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 21 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 22 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 23 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 24 | *****************************************************************************************************************************/ 25 | 26 | // Modified from stm32 core v2.0.0 27 | 28 | /* 29 | Copyright (c) 2017 Daniel Fekete 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all 39 | copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 47 | SOFTWARE. 48 | 49 | Copyright (c) 2019 STMicroelectronics 50 | Modified to support Arduino_Core_STM32 51 | */ 52 | 53 | /* Define to prevent recursive inclusion -------------------------------------*/ 54 | #ifndef HARDWARETIMER_H_ 55 | #define HARDWARETIMER_H_ 56 | 57 | /* Includes ------------------------------------------------------------------*/ 58 | #include "timer.h" 59 | 60 | #if defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY) 61 | 62 | #define TIMER_CHANNELS 4 // channel5 and channel 6 are not considered here has they don't have gpio output and they don't have interrupt 63 | 64 | typedef enum 65 | { 66 | TIMER_DISABLED, // == TIM_OCMODE_TIMING no output, useful for only-interrupt 67 | // Output Compare 68 | TIMER_OUTPUT_COMPARE, // == Obsolete, use TIMER_DISABLED instead. Kept for compatibility reason 69 | TIMER_OUTPUT_COMPARE_ACTIVE, // == TIM_OCMODE_ACTIVE pin is set high when counter == channel compare 70 | TIMER_OUTPUT_COMPARE_INACTIVE, // == TIM_OCMODE_INACTIVE pin is set low when counter == channel compare 71 | TIMER_OUTPUT_COMPARE_TOGGLE, // == TIM_OCMODE_TOGGLE pin toggles when counter == channel compare 72 | TIMER_OUTPUT_COMPARE_PWM1, // == TIM_OCMODE_PWM1 pin high when counter < channel compare, low otherwise 73 | TIMER_OUTPUT_COMPARE_PWM2, // == TIM_OCMODE_PWM2 pin low when counter < channel compare, high otherwise 74 | TIMER_OUTPUT_COMPARE_FORCED_ACTIVE, // == TIM_OCMODE_FORCED_ACTIVE pin always high 75 | TIMER_OUTPUT_COMPARE_FORCED_INACTIVE, // == TIM_OCMODE_FORCED_INACTIVE pin always low 76 | 77 | //Input capture 78 | TIMER_INPUT_CAPTURE_RISING, // == TIM_INPUTCHANNELPOLARITY_RISING 79 | TIMER_INPUT_CAPTURE_FALLING, // == TIM_INPUTCHANNELPOLARITY_FALLING 80 | TIMER_INPUT_CAPTURE_BOTHEDGE, // == TIM_INPUTCHANNELPOLARITY_BOTHEDGE 81 | 82 | // Used 2 channels for a single pin. One channel in TIM_INPUTCHANNELPOLARITY_RISING another channel in TIM_INPUTCHANNELPOLARITY_FALLING. 83 | // Channels must be used by pair: CH1 with CH2, or CH3 with CH4 84 | // This mode is very useful for Frequency and Dutycycle measurement 85 | TIMER_INPUT_FREQ_DUTY_MEASUREMENT, 86 | 87 | TIMER_NOT_USED = 0xFFFF // This must be the last item of this enum 88 | } TimerModes_t; 89 | 90 | typedef enum 91 | { 92 | TICK_FORMAT, // default 93 | MICROSEC_FORMAT, 94 | HERTZ_FORMAT, 95 | } TimerFormat_t; 96 | 97 | typedef enum 98 | { 99 | RESOLUTION_1B_COMPARE_FORMAT = 1, // used for Dutycycle: [0 .. 1] 100 | RESOLUTION_2B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 3] 101 | RESOLUTION_3B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 7] 102 | RESOLUTION_4B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 15] 103 | RESOLUTION_5B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 31] 104 | RESOLUTION_6B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 63] 105 | RESOLUTION_7B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 127] 106 | RESOLUTION_8B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 255] 107 | RESOLUTION_9B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 511] 108 | RESOLUTION_10B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 1023] 109 | RESOLUTION_11B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 2047] 110 | RESOLUTION_12B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 4095] 111 | RESOLUTION_13B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 8191] 112 | RESOLUTION_14B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 16383] 113 | RESOLUTION_15B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 32767] 114 | RESOLUTION_16B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 65535] 115 | 116 | TICK_COMPARE_FORMAT = 0x80, // default 117 | MICROSEC_COMPARE_FORMAT, 118 | HERTZ_COMPARE_FORMAT, 119 | PERCENT_COMPARE_FORMAT, // used for Dutycycle 120 | } TimerCompareFormat_t; 121 | 122 | #ifdef __cplusplus 123 | 124 | #include 125 | using callback_function_t = std::function; 126 | 127 | /* Class --------------------------------------------------------*/ 128 | class HardwareTimer 129 | { 130 | public: 131 | HardwareTimer(TIM_TypeDef *instance); 132 | ~HardwareTimer(); // destructor 133 | 134 | void pause(void); // Pause counter and all output channels 135 | void pauseChannel(uint32_t channel); // Timer is still running but channel (output and interrupt) is disabled 136 | void resume(void); // Resume counter and all output channels 137 | void resumeChannel(uint32_t channel); // Resume only one channel 138 | 139 | void setPrescaleFactor(uint32_t prescaler); // set prescaler register (which is factor value - 1) 140 | uint32_t getPrescaleFactor(); 141 | 142 | void setOverflow(uint32_t val, TimerFormat_t format = 143 | TICK_FORMAT); // set AutoReload register depending on format provided 144 | uint32_t getOverflow(TimerFormat_t format = TICK_FORMAT); // return overflow depending on format provided 145 | 146 | void setPWM(uint32_t channel, PinName pin, uint32_t frequency, uint32_t dutycycle, 147 | callback_function_t PeriodCallback = nullptr, 148 | callback_function_t CompareCallback = nullptr); // Set all in one command freq in HZ, Duty in percentage. Including both interrup. 149 | void setPWM(uint32_t channel, uint32_t pin, uint32_t frequency, uint32_t dutycycle, 150 | callback_function_t PeriodCallback = nullptr, callback_function_t CompareCallback = nullptr); 151 | 152 | void setCount(uint32_t val, TimerFormat_t format = 153 | TICK_FORMAT); // set timer counter to value 'val' depending on format provided 154 | uint32_t getCount(TimerFormat_t format = 155 | TICK_FORMAT); // return current counter value of timer depending on format provided 156 | 157 | void setMode(uint32_t channel, TimerModes_t mode, 158 | PinName pin = NC); // Configure timer channel with specified mode on specified pin if available 159 | void setMode(uint32_t channel, TimerModes_t mode, uint32_t pin); 160 | 161 | TimerModes_t getMode(uint32_t channel); // Retrieve configured mode 162 | 163 | void setPreloadEnable(bool value); // Configure overflow preload enable setting 164 | 165 | uint32_t getCaptureCompare(uint32_t channel, 166 | TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // return Capture/Compare register value of specified channel depending on format provided 167 | void setCaptureCompare(uint32_t channel, uint32_t compare, 168 | TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // set Compare register value of specified channel depending on format provided 169 | 170 | void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority); // set interrupt priority 171 | 172 | //Add interrupt to period update 173 | void attachInterrupt(callback_function_t 174 | callback); // Attach interrupt callback which will be called upon update event (timer rollover) 175 | void detachInterrupt(); // remove interrupt callback which was attached to update event 176 | bool hasInterrupt(); //returns true if a timer rollover interrupt has already been set 177 | //Add interrupt to capture/compare channel 178 | void attachInterrupt(uint32_t channel, 179 | callback_function_t callback); // Attach interrupt callback which will be called upon compare match event of specified channel 180 | void detachInterrupt(uint32_t 181 | channel); // remove interrupt callback which was attached to compare match event of specified channel 182 | bool hasInterrupt(uint32_t channel); //returns true if an interrupt has already been set on the channel compare match 183 | void timerHandleDeinit(); // Timer deinitialization 184 | 185 | // Refresh() is usefull while timer is running after some registers update 186 | void refresh( 187 | void); // Generate update event to force all registers (Autoreload, prescaler, compare) to be taken into account 188 | 189 | uint32_t getTimerClkFreq(); // return timer clock frequency in Hz. 190 | 191 | static void captureCompareCallback(TIM_HandleTypeDef 192 | *htim); // Generic Caputre and Compare callback which will call user callback 193 | static void updateCallback(TIM_HandleTypeDef 194 | *htim); // Generic Update (rollover) callback which will call user callback 195 | 196 | // The following function(s) are available for more advanced timer options 197 | TIM_HandleTypeDef *getHandle(); // return the handle address for HAL related configuration 198 | int getChannel(uint32_t channel); 199 | int getLLChannel(uint32_t channel); 200 | int getIT(uint32_t channel); 201 | int getAssociatedChannel(uint32_t channel); 202 | #if defined(TIM_CCER_CC1NE) 203 | bool isComplementaryChannel[TIMER_CHANNELS]; 204 | #endif 205 | private: 206 | TimerModes_t _ChannelMode[TIMER_CHANNELS]; 207 | timerObj_t _timerObj; 208 | callback_function_t callbacks[1 + 209 | TIMER_CHANNELS]; //Callbacks: 0 for update, 1-4 for channels. (channel5/channel6, if any, doesn't have interrupt) 210 | }; 211 | 212 | extern timerObj_t *HardwareTimer_Handle[TIMER_NUM]; 213 | 214 | extern timer_index_t get_timer_index(TIM_TypeDef *htim); 215 | 216 | #endif /* __cplusplus */ 217 | 218 | #endif // HAL_TIM_MODULE_ENABLED && !HAL_TIM_MODULE_ONLY 219 | #endif // HARDWARETIMER_H_ 220 | -------------------------------------------------------------------------------- /src/stm32/timer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | timer.h 3 | 4 | For Portenta_H7 boards 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 11 | unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks. 12 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 13 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 14 | This important feature is absolutely necessary for mission-critical tasks. 15 | 16 | Version: 1.4.0 17 | 18 | Version Modified By Date Comments 19 | ------- ----------- ---------- ----------- 20 | 1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7 21 | 1.3.0 K.Hoang 17/09/2021 Add PWM features and examples 22 | 1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples 23 | 1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug 24 | *****************************************************************************************************************************/ 25 | 26 | // Modified from stm32 core v2.0.0 27 | 28 | /* 29 | ******************************************************************************* 30 | Copyright (c) 2019, STMicroelectronics 31 | All rights reserved. 32 | 33 | This software component is licensed by ST under BSD 3-Clause license, 34 | the "License"; You may not use this file except in compliance with the 35 | License. You may obtain a copy of the License at: 36 | opensource.org/licenses/BSD-3-Clause 37 | 38 | ******************************************************************************* 39 | */ 40 | 41 | /* Define to prevent recursive inclusion -------------------------------------*/ 42 | #ifndef __TIMER_H 43 | #define __TIMER_H 44 | 45 | /* Includes ------------------------------------------------------------------*/ 46 | #include "PinNames.h" 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | #if defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY) 53 | 54 | /* Exported constants --------------------------------------------------------*/ 55 | #ifndef TIM_IRQ_PRIO 56 | #if (__CORTEX_M == 0x00U) 57 | #define TIM_IRQ_PRIO 3 58 | #else 59 | #define TIM_IRQ_PRIO 14 60 | #endif /* __CORTEX_M */ 61 | 62 | #endif /* TIM_IRQ_PRIO */ 63 | 64 | #ifndef TIM_IRQ_SUBPRIO 65 | #define TIM_IRQ_SUBPRIO 0 66 | #endif 67 | 68 | #if defined(TIM1_BASE) && !defined(TIM1_IRQn) 69 | #define TIM1_IRQn TIM1_UP_IRQn 70 | #define TIM1_IRQHandler TIM1_UP_IRQHandler 71 | #endif 72 | 73 | #if defined(TIM8_BASE) && !defined(TIM8_IRQn) 74 | #define TIM8_IRQn TIM8_UP_TIM13_IRQn 75 | #define TIM8_IRQHandler TIM8_UP_TIM13_IRQHandler 76 | #endif 77 | 78 | #if defined(TIM12_BASE) && !defined(TIM12_IRQn) 79 | #define TIM12_IRQn TIM8_BRK_TIM12_IRQn 80 | #define TIM12_IRQHandler TIM8_BRK_TIM12_IRQHandler 81 | #endif 82 | 83 | #if defined(TIM13_BASE) && !defined(TIM13_IRQn) 84 | #define TIM13_IRQn TIM8_UP_TIM13_IRQn 85 | #endif 86 | 87 | #if defined(TIM14_BASE) && !defined(TIM14_IRQn) 88 | #define TIM14_IRQn TIM8_TRG_COM_TIM14_IRQn 89 | #define TIM14_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler 90 | #endif 91 | 92 | 93 | typedef enum 94 | { 95 | #if defined(TIM1_BASE) 96 | TIMER1_INDEX, 97 | #endif 98 | #if defined(TIM2_BASE) 99 | TIMER2_INDEX, 100 | #endif 101 | #if defined(TIM3_BASE) 102 | TIMER3_INDEX, 103 | #endif 104 | #if defined(TIM4_BASE) 105 | TIMER4_INDEX, 106 | #endif 107 | #if defined(TIM5_BASE) 108 | TIMER5_INDEX, 109 | #endif 110 | #if defined(TIM6_BASE) 111 | TIMER6_INDEX, 112 | #endif 113 | #if defined(TIM7_BASE) 114 | TIMER7_INDEX, 115 | #endif 116 | #if defined(TIM8_BASE) 117 | TIMER8_INDEX, 118 | #endif 119 | #if defined(TIM9_BASE) 120 | TIMER9_INDEX, 121 | #endif 122 | #if defined(TIM10_BASE) 123 | TIMER10_INDEX, 124 | #endif 125 | #if defined(TIM11_BASE) 126 | TIMER11_INDEX, 127 | #endif 128 | #if defined(TIM12_BASE) 129 | TIMER12_INDEX, 130 | #endif 131 | #if defined(TIM13_BASE) 132 | TIMER13_INDEX, 133 | #endif 134 | #if defined(TIM14_BASE) 135 | TIMER14_INDEX, 136 | #endif 137 | #if defined(TIM15_BASE) 138 | TIMER15_INDEX, 139 | #endif 140 | #if defined(TIM16_BASE) 141 | TIMER16_INDEX, 142 | #endif 143 | #if defined(TIM17_BASE) 144 | TIMER17_INDEX, 145 | #endif 146 | #if defined(TIM18_BASE) 147 | TIMER18_INDEX, 148 | #endif 149 | #if defined(TIM19_BASE) 150 | TIMER19_INDEX, 151 | #endif 152 | #if defined(TIM20_BASE) 153 | TIMER20_INDEX, 154 | #endif 155 | #if defined(TIM21_BASE) 156 | TIMER21_INDEX, 157 | #endif 158 | #if defined(TIM22_BASE) 159 | TIMER22_INDEX, 160 | #endif 161 | 162 | TIMER_NUM, 163 | UNKNOWN_TIMER = 0XFFFF 164 | } timer_index_t; 165 | 166 | 167 | // This structure is used to be able to get HardwareTimer instance (C++ class) 168 | // from handler (C structure) specially for interrupt management 169 | typedef struct 170 | { 171 | // Those 2 first fields must remain in this order at the beginning of the structure 172 | void *__this; 173 | TIM_HandleTypeDef handle; 174 | uint32_t preemptPriority; 175 | uint32_t subPriority; 176 | } timerObj_t; 177 | 178 | /* Exported functions ------------------------------------------------------- */ 179 | timerObj_t *get_timer_obj(TIM_HandleTypeDef *htim); 180 | 181 | void enableTimerClock(TIM_HandleTypeDef *htim); 182 | void disableTimerClock(TIM_HandleTypeDef *htim); 183 | 184 | uint32_t getTimerIrq(TIM_TypeDef *tim); 185 | uint8_t getTimerClkSrc(TIM_TypeDef *tim); 186 | 187 | IRQn_Type getTimerUpIrq(TIM_TypeDef *tim); 188 | IRQn_Type getTimerCCIrq(TIM_TypeDef *tim); 189 | 190 | #endif /* HAL_TIM_MODULE_ENABLED && !HAL_TIM_MODULE_ONLY */ 191 | 192 | #ifdef __cplusplus 193 | } 194 | #endif 195 | 196 | #endif /* __TIMER_H */ 197 | 198 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 199 | -------------------------------------------------------------------------------- /utils/astyle_library.conf: -------------------------------------------------------------------------------- 1 | # Code formatting rules for Arduino libraries, modified from for KH libraries: 2 | # 3 | # https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf 4 | # 5 | 6 | # astyle --style=allman -s2 -t2 -C -S -xW -Y -M120 -f -p -xg -H -xb -c --xC120 -xL *.h *.cpp *.ino 7 | 8 | --mode=c 9 | --lineend=linux 10 | --style=allman 11 | 12 | # -r or -R 13 | #--recursive 14 | 15 | # -c => Converts tabs into spaces 16 | convert-tabs 17 | 18 | # -s2 => 2 spaces indentation 19 | --indent=spaces=2 20 | 21 | # -t2 => tab =2 spaces 22 | #--indent=tab=2 23 | 24 | # -C 25 | --indent-classes 26 | 27 | # -S 28 | --indent-switches 29 | 30 | # -xW 31 | --indent-preproc-block 32 | 33 | # -Y => indent classes, switches (and cases), comments starting at column 1 34 | --indent-col1-comments 35 | 36 | # -M120 => maximum of 120 spaces to indent a continuation line 37 | --max-continuation-indent=120 38 | 39 | # -xC120 => max‑code‑length will break a line if the code exceeds # characters 40 | --max-code-length=120 41 | 42 | # -f => 43 | --break-blocks 44 | 45 | # -p => put a space around operators 46 | --pad-oper 47 | 48 | # -xg => Insert space padding after commas 49 | --pad-comma 50 | 51 | # -H => put a space after if/for/while 52 | pad-header 53 | 54 | # -xb => Break one line headers (e.g. if/for/while) 55 | --break-one-line-headers 56 | 57 | # -c => Converts tabs into spaces 58 | #--convert-tabs 59 | 60 | # if you like one-liners, keep them 61 | #keep-one-line-statements 62 | 63 | # -xV 64 | --attach-closing-while 65 | 66 | #unpad-paren 67 | 68 | # -xp 69 | remove-comment-prefix 70 | 71 | -------------------------------------------------------------------------------- /utils/restyle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for dir in . ; do 4 | find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.ino" \) -exec astyle --suffix=none --options=./utils/astyle_library.conf \{\} \; 5 | done 6 | 7 | --------------------------------------------------------------------------------