├── .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 └── rp2040 │ └── hardware │ └── rp2040 │ ├── 1.2.1 │ └── platform.txt │ ├── 1.2.2 │ └── platform.txt │ ├── 1.3.0 │ └── platform.txt │ ├── 1.3.1 │ ├── cores │ │ └── rp2040 │ │ │ └── Arduino.h │ └── platform.txt │ └── 1.4.0 │ ├── cores │ └── rp2040 │ │ └── Arduino.h │ └── platform.txt ├── README.md ├── changelog.md ├── examples ├── Argument_Complex │ └── Argument_Complex.ino ├── Argument_None │ └── Argument_None.ino ├── Argument_Simple │ └── Argument_Simple.ino ├── Change_Interval │ └── Change_Interval.ino ├── ISR_16_Timers_Array_Complex │ └── ISR_16_Timers_Array_Complex.ino ├── ISR_Timers_Array_Simple │ └── ISR_Timers_Array_Simple.ino ├── RPM_Measure │ └── RPM_Measure.ino ├── SwitchDebounce │ └── SwitchDebounce.ino ├── TimerInterruptTest │ └── TimerInterruptTest.ino └── multiFileProject │ ├── multiFileProject.cpp │ ├── multiFileProject.h │ └── multiFileProject.ino ├── keywords.txt ├── library.json ├── library.properties ├── platformio └── platformio.ini ├── src ├── RPi_Pico_ISR_Timer-Impl.h ├── RPi_Pico_ISR_Timer.h ├── RPi_Pico_ISR_Timer.hpp ├── RPi_Pico_TimerInterrupt.h └── TimerInterrupt_Generic_Debug.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.19) or Platform.io version 39 | * `RP2040` Core Version (e.g. RP2040 core v2.6.3) 40 | * `RP2040` Board type (e.g. RASPBERRY_PI_PICO, RASPBERRY_PI_PICO_W, ADAFRUIT_FEATHER_RP2040, GENERIC_RP2040, etc.) 41 | * Contextual information (e.g. what you were trying to achieve) 42 | * Simplest possible steps to reproduce 43 | * Anything that might be relevant in your opinion, such as: 44 | * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` 45 | * Network configuration 46 | 47 | 48 | ### Example 49 | 50 | ``` 51 | Arduino IDE version: 1.8.19 52 | RP2040 core v2.6.3 53 | RASPBERRY_PI_PICO Module 54 | OS: Ubuntu 20.04 LTS 55 | 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 56 | 57 | Context: 58 | I encountered a crash while using this library 59 | Steps to reproduce: 60 | 1. ... 61 | 2. ... 62 | 3. ... 63 | 4. ... 64 | ``` 65 | 66 | ### Additional context 67 | 68 | Add any other context about the problem here. 69 | 70 | --- 71 | 72 | ### Sending Feature Requests 73 | 74 | Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. 75 | 76 | There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/RPI_PICO_TimerInterrupt/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. 77 | 78 | --- 79 | 80 | ### Sending Pull Requests 81 | 82 | Pull Requests with changes and fixes are also welcome! 83 | 84 | Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux) 85 | 86 | 1. Change directory to the library GitHub 87 | 88 | ``` 89 | xy@xy-Inspiron-3593:~$ cd Arduino/xy/RPI_PICO_TimerInterrupt_GitHub/ 90 | xy@xy-Inspiron-3593:~/Arduino/xy/RPI_PICO_TimerInterrupt_GitHub$ 91 | ``` 92 | 93 | 2. Issue astyle command 94 | 95 | ``` 96 | xy@xy-Inspiron-3593:~/Arduino/xy/RPI_PICO_TimerInterrupt_GitHub$ bash utils/restyle.sh 97 | ``` 98 | 99 | 100 | -------------------------------------------------------------------------------- /.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 | 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | ### Additional context 23 | 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /.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 RPI_PICO_TimerInterrupt 2 | 3 | ### Reporting Bugs 4 | 5 | Please report bugs in [RPI_PICO_TimerInterrupt Issues](https://github.com/khoih-prog/RPI_PICO_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/RPI_PICO_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/RPI_PICO_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 | * `RP2040` Core Version (e.g. RP2040 core v2.6.3) 19 | * `RP2040` Board type (e.g. RASPBERRY_PI_PICO, RASPBERRY_PI_PICO_W, ADAFRUIT_FEATHER_RP2040, GENERIC_RP2040, 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 | RP2040 core v2.6.3 32 | RASPBERRY_PI_PICO Module 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/RPI_PICO_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/RPI_PICO_TimerInterrupt_GitHub/ 69 | xy@xy-Inspiron-3593:~/Arduino/xy/RPI_PICO_TimerInterrupt_GitHub$ 70 | ``` 71 | 72 | 2. Issue astyle command 73 | 74 | ``` 75 | xy@xy-Inspiron-3593:~/Arduino/xy/RPI_PICO_TimerInterrupt_GitHub$ bash utils/restyle.sh 76 | ``` 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /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/rp2040/hardware/rp2040/1.2.1/platform.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Earle F. Philhower, III 2 | # 3 | # Raspberry Pi RP2040 Core platform file 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | # See the GNU Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | # For more info: 20 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification 21 | 22 | name=Raspberry Pi RP2040 Boards(1.2.1) 23 | version=1.2.1 24 | 25 | 26 | 27 | 28 | 29 | 30 | compiler.path={runtime.tools.pqt-gcc.path}/bin/ 31 | 32 | # Compile variables 33 | # ----------------- 34 | 35 | compiler.warning_flags=-w 36 | compiler.warning_flags.none=-w 37 | compiler.warning_flags.default= 38 | compiler.warning_flags.more=-Wall 39 | compiler.warning_flags.all=-Wall -Wextra 40 | 41 | compiler.defines={build.led} 42 | compiler.includes="-I{runtime.platform.path}/pico_base/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_unique_id/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_platform/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_base/include/" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_timer/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_stdlib/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_gpio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_i2c/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_flash/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_base/include" "-I{runtime.platform.path}/pico-examples/build/generated/pico_base" "-I{runtime.platform.path}/pico-sdk/src/boards/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_platform/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_base/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_structs/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_claim/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_sync/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_uart/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_divider/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_time/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_timer/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_sync/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_util/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_runtime/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_clocks/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_resets/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_watchdog/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_xosc/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pll/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_vreg/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_irq/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_printf/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_bootrom/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_bit_ops/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_divider/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_double/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_int64_ops/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_float/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_dma/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio_uart/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/lib/tinyusb/src/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio_usb/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_spi/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pwm/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_adc/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_multicore/include" "-I{runtime.platform.path}/cores/rp2040/api/deprecated-avr-comp/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_multicore/include" "-I{runtime.platform.path}/pico-extras/src/rp2_common/pico_audio_i2s/include" "-I{runtime.platform.path}/pico-extras/src/common/pico_audio/include" "-I{runtime.platform.path}/pico-extras/src/common/pico_util_buffer/include" 43 | compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections 44 | compiler.wrap=-Wl,--wrap=acos -Wl,--wrap=acosf -Wl,--wrap=acosh -Wl,--wrap=acoshf -Wl,--wrap=__aeabi_cdcmpeq -Wl,--wrap=__aeabi_cdcmple -Wl,--wrap=__aeabi_cdrcmple -Wl,--wrap=__aeabi_cfcmpeq -Wl,--wrap=__aeabi_cfcmple -Wl,--wrap=__aeabi_cfrcmple -Wl,--wrap=__aeabi_d2f -Wl,--wrap=__aeabi_d2iz -Wl,--wrap=__aeabi_d2lz -Wl,--wrap=__aeabi_d2uiz -Wl,--wrap=__aeabi_d2ulz -Wl,--wrap=__aeabi_dadd -Wl,--wrap=__aeabi_dcmpeq -Wl,--wrap=__aeabi_dcmpge -Wl,--wrap=__aeabi_dcmpgt -Wl,--wrap=__aeabi_dcmple -Wl,--wrap=__aeabi_dcmplt -Wl,--wrap=__aeabi_dcmpun -Wl,--wrap=__aeabi_ddiv -Wl,--wrap=__aeabi_dmul -Wl,--wrap=__aeabi_drsub -Wl,--wrap=__aeabi_dsub -Wl,--wrap=__aeabi_f2d -Wl,--wrap=__aeabi_f2iz -Wl,--wrap=__aeabi_f2lz -Wl,--wrap=__aeabi_f2uiz -Wl,--wrap=__aeabi_f2ulz -Wl,--wrap=__aeabi_fadd -Wl,--wrap=__aeabi_fcmpeq -Wl,--wrap=__aeabi_fcmpge -Wl,--wrap=__aeabi_fcmpgt -Wl,--wrap=__aeabi_fcmple -Wl,--wrap=__aeabi_fcmplt -Wl,--wrap=__aeabi_fcmpun -Wl,--wrap=__aeabi_fdiv -Wl,--wrap=__aeabi_fmul -Wl,--wrap=__aeabi_frsub -Wl,--wrap=__aeabi_fsub -Wl,--wrap=__aeabi_i2d -Wl,--wrap=__aeabi_i2f -Wl,--wrap=__aeabi_idiv -Wl,--wrap=__aeabi_idivmod -Wl,--wrap=__aeabi_l2d -Wl,--wrap=__aeabi_l2f -Wl,--wrap=__aeabi_ldivmod -Wl,--wrap=__aeabi_lmul -Wl,--wrap=__aeabi_memcpy -Wl,--wrap=__aeabi_memcpy4 -Wl,--wrap=__aeabi_memcpy8 -Wl,--wrap=__aeabi_memset -Wl,--wrap=__aeabi_memset4 -Wl,--wrap=__aeabi_memset8 -Wl,--wrap=__aeabi_ui2d -Wl,--wrap=__aeabi_ui2f -Wl,--wrap=__aeabi_uidiv -Wl,--wrap=__aeabi_uidivmod -Wl,--wrap=__aeabi_ul2d -Wl,--wrap=__aeabi_ul2f -Wl,--wrap=__aeabi_uldivmod -Wl,--wrap=asin -Wl,--wrap=asinf -Wl,--wrap=asinh -Wl,--wrap=asinhf -Wl,--wrap=atan -Wl,--wrap=atan2 -Wl,--wrap=atan2f -Wl,--wrap=atanf -Wl,--wrap=atanh -Wl,--wrap=atanhf -Wl,--wrap=calloc -Wl,--wrap=cbrt -Wl,--wrap=cbrtf -Wl,--wrap=ceil -Wl,--wrap=ceilf -Wl,--wrap=__clz -Wl,--wrap=__clzdi2 -Wl,--wrap=__clzl -Wl,--wrap=__clzll -Wl,--wrap=__clzsi2 -Wl,--wrap=copysign -Wl,--wrap=copysignf -Wl,--wrap=cos -Wl,--wrap=cosf -Wl,--wrap=cosh -Wl,--wrap=coshf -Wl,--wrap=__ctzdi2 -Wl,--wrap=__ctzsi2 -Wl,--wrap=drem -Wl,--wrap=dremf -Wl,--wrap=exp -Wl,--wrap=exp10 -Wl,--wrap=exp10f -Wl,--wrap=exp2 -Wl,--wrap=exp2f -Wl,--wrap=expf -Wl,--wrap=expm1 -Wl,--wrap=expm1f -Wl,--wrap=floor -Wl,--wrap=floorf -Wl,--wrap=fma -Wl,--wrap=fmaf -Wl,--wrap=fmod -Wl,--wrap=fmodf -Wl,--wrap=free -Wl,--wrap=hypot -Wl,--wrap=hypotf -Wl,--wrap=ldexp -Wl,--wrap=ldexpf -Wl,--wrap=log -Wl,--wrap=log10 -Wl,--wrap=log10f -Wl,--wrap=log1p -Wl,--wrap=log1pf -Wl,--wrap=log2 -Wl,--wrap=log2f -Wl,--wrap=logf -Wl,--wrap=malloc -Wl,--wrap=memcpy -Wl,--wrap=memset -Wl,--wrap=__popcountdi2 -Wl,--wrap=__popcountsi2 -Wl,--wrap=pow -Wl,--wrap=powf -Wl,--wrap=powint -Wl,--wrap=powintf -Wl,--wrap=remainder -Wl,--wrap=remainderf -Wl,--wrap=remquo -Wl,--wrap=remquof -Wl,--wrap=round -Wl,--wrap=roundf -Wl,--wrap=sin -Wl,--wrap=sincos -Wl,--wrap=sincosf -Wl,--wrap=sinf -Wl,--wrap=sinh -Wl,--wrap=sinhf -Wl,--wrap=sqrt -Wl,--wrap=sqrtf -Wl,--wrap=tan -Wl,--wrap=tanf -Wl,--wrap=tanh -Wl,--wrap=tanhf -Wl,--wrap=trunc -Wl,--wrap=truncf 45 | 46 | compiler.c.cmd=arm-none-eabi-gcc 47 | compiler.c.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -std=gnu17 -g 48 | compiler.c.elf.cmd=arm-none-eabi-g++ 49 | compiler.c.elf.flags={compiler.defines} {compiler.flags} -Wl,--gc-sections -u _printf_float -u _scanf_float 50 | compiler.S.cmd=arm-none-eabi-gcc 51 | compiler.S.flags=-c -g -x assembler-with-cpp -MMD {compiler.includes} -g 52 | compiler.cpp.cmd=arm-none-eabi-g++ 53 | compiler.cpp.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -std=gnu++17 -g 54 | 55 | 56 | compiler.ar.cmd=arm-none-eabi-ar 57 | compiler.ar.flags=rcs 58 | compiler.objcopy.cmd=arm-none-eabi-objcopy 59 | compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 60 | compiler.elf2hex.bin.flags=-O binary 61 | compiler.elf2hex.hex.flags=-O ihex -R .eeprom 62 | compiler.elf2hex.cmd=arm-none-eabi-objcopy 63 | compiler.ldflags={compiler.wrap} -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common 64 | compiler.size.cmd=arm-none-eabi-size 65 | compiler.define=-DARDUINO= 66 | compiler.readelf.cmd=arm-none-eabi-readelf 67 | 68 | # this can be overriden in boards.txt 69 | build.extra_flags= 70 | 71 | # These can be overridden in platform.local.txt 72 | compiler.c.extra_flags= 73 | compiler.c.elf.extra_flags= 74 | compiler.cpp.extra_flags= 75 | compiler.S.extra_flags= 76 | compiler.ar.extra_flags= 77 | compiler.elf2hex.extra_flags= 78 | 79 | # Board configuration, set in boards.txt. Present here to ensure substitution works 80 | build.flash_length= 81 | build.eeprom_start= 82 | build.fs_start= 83 | build.fs_end= 84 | 85 | build.boot2=boot2_generic_03h_4_padded_checksum 86 | 87 | # Allow Pico boards do be auto-discovered by the IDE 88 | discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/discovery.py" 89 | 90 | 91 | # Compile patterns 92 | # ---------------- 93 | 94 | ## Compile c files 95 | ## KH Add -DBOARD_NAME="{build.board}" 96 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 97 | 98 | ## Compile c++ files 99 | ## KH Add -DBOARD_NAME="{build.board}" 100 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 101 | 102 | ## Compile S files 103 | ## KH Add -DBOARD_NAME="{build.board}" 104 | recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 105 | 106 | ## Create archives 107 | # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value 108 | archive_file_path={build.path}/{archive_file} 109 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" 110 | 111 | ## Combine gc-sections, archives, and objects 112 | recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/simplesub.py" --input "{runtime.platform.path}/lib/memmap_default.ld" --out "{build.path}/memmap_default.ld" --sub __FLASH_LENGTH__ {build.flash_length} --sub __EEPROM_START__ {build.eeprom_start} --sub __FS_START__ {build.fs_start} --sub __FS_END__ {build.fs_end} 113 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nosys.specs -Wl,--start-group {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "{runtime.platform.path}/lib/libpico.a" -lm "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "{runtime.platform.path}/assembly/{build.boot2}.S" -lc -lstdc++ -Wl,--end-group 114 | 115 | ## Create output (UF2 file) 116 | recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" 117 | 118 | build.preferred_out_format=uf2 119 | 120 | ## Save hex 121 | recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} 122 | recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} 123 | 124 | ## Compute size 125 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" 126 | recipe.size.regex=^(?:\.boot2|\.text|\.rodata|\.ARM\.extab|\.ARM\.exidx)\s+([0-9]+).* 127 | recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_data)\s+([0-9]+).* 128 | 129 | tools.uf2conv.path= 130 | # Because the variable expansion doesn't allow one tool to find another, the following lines 131 | # will point to "{runtime.platform.path}/tools/python3/python3" in GIT and 132 | # "{runtime.tools.pqt-python3.path}/python3" for JSON board manager releases. 133 | tools.uf2conv.cmd={runtime.tools.pqt-python3.path}/python3 134 | 135 | tools.uf2conv.upload.protocol=uf2 136 | tools.uf2conv.upload.params.verbose= 137 | tools.uf2conv.upload.params.quiet= 138 | tools.uf2conv.upload.pattern="{cmd}" "{runtime.platform.path}/tools/uf2conv.py" --serial "{serial.port}" --family RP2040 --deploy "{build.path}/{build.project_name}.uf2" 139 | 140 | 141 | tools.picoprobe.cmd={runtime.tools.pqt-openocd.path} 142 | 143 | tools.picoprobe.upload.protocol=picoprobe 144 | tools.picoprobe.upload.params.verbose= 145 | tools.picoprobe.upload.params.quiet= 146 | tools.picoprobe.upload.pattern="{cmd}/bin/openocd" -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "program {build.path}/{build.project_name}.elf verify reset exit" 147 | -------------------------------------------------------------------------------- /Packages_Patches/rp2040/hardware/rp2040/1.2.2/platform.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Earle F. Philhower, III 2 | # 3 | # Raspberry Pi RP2040 Core platform file 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | # See the GNU Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | # For more info: 20 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification 21 | 22 | name=Raspberry Pi RP2040 Boards(1.2.2) 23 | version=1.2.2 24 | 25 | 26 | 27 | 28 | 29 | 30 | compiler.path={runtime.tools.pqt-gcc.path}/bin/ 31 | 32 | # Compile variables 33 | # ----------------- 34 | 35 | compiler.warning_flags=-w 36 | compiler.warning_flags.none=-w 37 | compiler.warning_flags.default= 38 | compiler.warning_flags.more=-Wall 39 | compiler.warning_flags.all=-Wall -Wextra 40 | 41 | compiler.defines={build.led} 42 | compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" 43 | compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections -fno-exceptions 44 | compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt" 45 | 46 | compiler.c.cmd=arm-none-eabi-gcc 47 | compiler.c.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -std=gnu17 -g 48 | compiler.c.elf.cmd=arm-none-eabi-g++ 49 | compiler.c.elf.flags={compiler.defines} {compiler.flags} -Wl,--gc-sections -u _printf_float -u _scanf_float 50 | compiler.S.cmd=arm-none-eabi-gcc 51 | compiler.S.flags=-c -g -x assembler-with-cpp -MMD {compiler.includes} -g 52 | compiler.cpp.cmd=arm-none-eabi-g++ 53 | compiler.cpp.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -fno-rtti -std=gnu++17 -g 54 | 55 | compiler.ar.cmd=arm-none-eabi-ar 56 | compiler.ar.flags=rcs 57 | compiler.objcopy.cmd=arm-none-eabi-objcopy 58 | compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 59 | compiler.elf2hex.bin.flags=-O binary 60 | compiler.elf2hex.hex.flags=-O ihex -R .eeprom 61 | compiler.elf2hex.cmd=arm-none-eabi-objcopy 62 | compiler.ldflags={compiler.wrap} -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common 63 | compiler.size.cmd=arm-none-eabi-size 64 | compiler.define=-DARDUINO= 65 | compiler.readelf.cmd=arm-none-eabi-readelf 66 | 67 | # this can be overriden in boards.txt 68 | build.extra_flags= 69 | 70 | # These can be overridden in platform.local.txt 71 | compiler.c.extra_flags= 72 | compiler.c.elf.extra_flags= 73 | compiler.cpp.extra_flags= 74 | compiler.S.extra_flags= 75 | compiler.ar.extra_flags= 76 | compiler.elf2hex.extra_flags= 77 | 78 | # Board configuration, set in boards.txt. Present here to ensure substitution works 79 | build.flash_length= 80 | build.eeprom_start= 81 | build.fs_start= 82 | build.fs_end= 83 | 84 | build.boot2=boot2_generic_03h_4_padded_checksum 85 | 86 | # Allow Pico boards do be auto-discovered by the IDE 87 | discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/discovery.py" 88 | 89 | 90 | # Compile patterns 91 | # ---------------- 92 | 93 | ## Compile c files 94 | ## KH Add -DBOARD_NAME="{build.board}" 95 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 96 | 97 | ## Compile c++ files 98 | ## KH Add -DBOARD_NAME="{build.board}" 99 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 100 | 101 | ## Compile S files 102 | ## KH Add -DBOARD_NAME="{build.board}" 103 | recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 104 | 105 | ## Create archives 106 | # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value 107 | archive_file_path={build.path}/{archive_file} 108 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" 109 | 110 | ## Combine gc-sections, archives, and objects 111 | recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/simplesub.py" --input "{runtime.platform.path}/lib/memmap_default.ld" --out "{build.path}/memmap_default.ld" --sub __FLASH_LENGTH__ {build.flash_length} --sub __EEPROM_START__ {build.eeprom_start} --sub __FS_START__ {build.fs_start} --sub __FS_END__ {build.fs_end} 112 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nosys.specs -Wl,--start-group {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "{runtime.platform.path}/lib/libpico.a" -lm "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "{runtime.platform.path}/assembly/{build.boot2}.S" -lc -lstdc++ -Wl,--end-group 113 | 114 | ## Create output (UF2 file) 115 | recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" 116 | 117 | build.preferred_out_format=uf2 118 | 119 | ## Save hex 120 | recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} 121 | recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} 122 | 123 | ## Compute size 124 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" 125 | recipe.size.regex=^(?:\.boot2|\.text|\.rodata|\.ARM\.extab|\.ARM\.exidx)\s+([0-9]+).* 126 | recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_data)\s+([0-9]+).* 127 | 128 | tools.uf2conv.path= 129 | # Because the variable expansion doesn't allow one tool to find another, the following lines 130 | # will point to "{runtime.platform.path}/tools/python3/python3" in GIT and 131 | # "{runtime.tools.pqt-python3.path}/python3" for JSON board manager releases. 132 | tools.uf2conv.cmd={runtime.tools.pqt-python3.path}/python3 133 | 134 | tools.uf2conv.upload.protocol=uf2 135 | tools.uf2conv.upload.params.verbose= 136 | tools.uf2conv.upload.params.quiet= 137 | tools.uf2conv.upload.pattern="{cmd}" "{runtime.platform.path}/tools/uf2conv.py" --serial "{serial.port}" --family RP2040 --deploy "{build.path}/{build.project_name}.uf2" 138 | 139 | 140 | tools.picoprobe.cmd={runtime.tools.pqt-openocd.path} 141 | 142 | tools.picoprobe.upload.protocol=picoprobe 143 | tools.picoprobe.upload.params.verbose= 144 | tools.picoprobe.upload.params.quiet= 145 | tools.picoprobe.upload.pattern="{cmd}/bin/openocd" -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "program {build.path}/{build.project_name}.elf verify reset exit" 146 | -------------------------------------------------------------------------------- /Packages_Patches/rp2040/hardware/rp2040/1.3.0/platform.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Earle F. Philhower, III 2 | # 3 | # Raspberry Pi RP2040 Core platform file 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | # See the GNU Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | # For more info: 20 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification 21 | 22 | name=Raspberry Pi RP2040 Boards(1.3.0) 23 | version=1.3.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | compiler.path={runtime.tools.pqt-gcc.path}/bin/ 31 | 32 | # Compile variables 33 | # ----------------- 34 | 35 | compiler.warning_flags=-w 36 | compiler.warning_flags.none=-w 37 | compiler.warning_flags.default= 38 | compiler.warning_flags.more=-Wall 39 | compiler.warning_flags.all=-Wall -Wextra 40 | 41 | compiler.defines={build.led} 42 | compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" 43 | compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections -fno-exceptions 44 | compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt" 45 | 46 | compiler.c.cmd=arm-none-eabi-gcc 47 | compiler.c.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -std=gnu17 -g 48 | compiler.c.elf.cmd=arm-none-eabi-g++ 49 | compiler.c.elf.flags={compiler.defines} {compiler.flags} -Wl,--gc-sections -u _printf_float -u _scanf_float 50 | compiler.S.cmd=arm-none-eabi-gcc 51 | compiler.S.flags=-c -g -x assembler-with-cpp -MMD {compiler.includes} -g 52 | compiler.cpp.cmd=arm-none-eabi-g++ 53 | compiler.cpp.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -fno-rtti -std=gnu++17 -g 54 | 55 | compiler.ar.cmd=arm-none-eabi-ar 56 | compiler.ar.flags=rcs 57 | compiler.objcopy.cmd=arm-none-eabi-objcopy 58 | compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 59 | compiler.elf2hex.bin.flags=-O binary 60 | compiler.elf2hex.hex.flags=-O ihex -R .eeprom 61 | compiler.elf2hex.cmd=arm-none-eabi-objcopy 62 | compiler.ldflags={compiler.wrap} -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common 63 | compiler.size.cmd=arm-none-eabi-size 64 | compiler.define=-DARDUINO= 65 | compiler.readelf.cmd=arm-none-eabi-readelf 66 | 67 | # this can be overriden in boards.txt 68 | build.extra_flags= 69 | 70 | # These can be overridden in platform.local.txt 71 | compiler.c.extra_flags= 72 | compiler.c.elf.extra_flags= 73 | compiler.cpp.extra_flags= 74 | compiler.S.extra_flags= 75 | compiler.ar.extra_flags= 76 | compiler.elf2hex.extra_flags= 77 | 78 | # Board configuration, set in boards.txt. Present here to ensure substitution works 79 | build.flash_length= 80 | build.eeprom_start= 81 | build.fs_start= 82 | build.fs_end= 83 | 84 | build.boot2=boot2_generic_03h_4_padded_checksum 85 | 86 | # Allow Pico boards do be auto-discovered by the IDE 87 | discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/discovery.py" 88 | 89 | 90 | # Compile patterns 91 | # ---------------- 92 | 93 | ## Compile c files 94 | ## Add -DBOARD_NAME="{build.board}" 95 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 96 | 97 | ## Compile c++ files 98 | ## Add -DBOARD_NAME="{build.board}" 99 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 100 | 101 | ## Compile S files 102 | ## Add -DBOARD_NAME="{build.board}" 103 | recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 104 | 105 | ## Create archives 106 | # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value 107 | archive_file_path={build.path}/{archive_file} 108 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" 109 | 110 | ## Combine gc-sections, archives, and objects 111 | recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/simplesub.py" --input "{runtime.platform.path}/lib/memmap_default.ld" --out "{build.path}/memmap_default.ld" --sub __FLASH_LENGTH__ {build.flash_length} --sub __EEPROM_START__ {build.eeprom_start} --sub __FS_START__ {build.fs_start} --sub __FS_END__ {build.fs_end} 112 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nosys.specs -Wl,--start-group {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "{runtime.platform.path}/lib/libpico.a" -lm "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "{runtime.platform.path}/assembly/{build.boot2}.S" -lc -lstdc++ -Wl,--end-group 113 | 114 | ## Create output (UF2 file) 115 | recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" 116 | 117 | build.preferred_out_format=uf2 118 | 119 | ## Save hex 120 | recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} 121 | recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} 122 | 123 | ## Compute size 124 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" 125 | recipe.size.regex=^(?:\.boot2|\.text|\.rodata|\.ARM\.extab|\.ARM\.exidx)\s+([0-9]+).* 126 | recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_data)\s+([0-9]+).* 127 | 128 | tools.uf2conv.path= 129 | # Because the variable expansion doesn't allow one tool to find another, the following lines 130 | # will point to "{runtime.platform.path}/tools/python3/python3" in GIT and 131 | # "{runtime.tools.pqt-python3.path}/python3" for JSON board manager releases. 132 | tools.uf2conv.cmd={runtime.tools.pqt-python3.path}/python3 133 | 134 | tools.uf2conv.upload.protocol=uf2 135 | tools.uf2conv.upload.params.verbose= 136 | tools.uf2conv.upload.params.quiet= 137 | tools.uf2conv.upload.pattern="{cmd}" "{runtime.platform.path}/tools/uf2conv.py" --serial "{serial.port}" --family RP2040 --deploy "{build.path}/{build.project_name}.uf2" 138 | 139 | 140 | tools.picoprobe.cmd={runtime.tools.pqt-openocd.path} 141 | 142 | tools.picoprobe.upload.protocol=picoprobe 143 | tools.picoprobe.upload.params.verbose= 144 | tools.picoprobe.upload.params.quiet= 145 | tools.picoprobe.upload.pattern="{cmd}/bin/openocd" -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "program {build.path}/{build.project_name}.elf verify reset exit" 146 | -------------------------------------------------------------------------------- /Packages_Patches/rp2040/hardware/rp2040/1.3.1/cores/rp2040/Arduino.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Arduino header for the Raspberry Pi Pico RP2040 3 | * 4 | * Copyright (c) 2021 Earle F. Philhower, III 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef Arduino_h 22 | #define Arduino_h 23 | 24 | #include 25 | #include 26 | #include 27 | // Wacky deprecated AVR compatibilty functions 28 | #include "stdlib_noniso.h" 29 | 30 | #include "api/ArduinoAPI.h" 31 | #include 32 | 33 | 34 | // Required for the port*Register macros 35 | #include "hardware/gpio.h" 36 | 37 | #include "debug_internal.h" 38 | 39 | #ifdef __cplusplus 40 | extern "C"{ 41 | #endif // __cplusplus 42 | 43 | // For compatibility to many platforms and libraries 44 | #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) 45 | #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) 46 | #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) 47 | 48 | // Disable/reenable all interrupts. Safely handles nested disables 49 | void interrupts(); 50 | void noInterrupts(); 51 | 52 | // GPIO change/value interrupts 53 | void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode); 54 | void detachInterrupt(pin_size_t pin); 55 | 56 | // AVR compatibilty macros...naughty and accesses the HW directly 57 | #define digitalPinToPort(pin) (0) 58 | #define digitalPinToBitMask(pin) (1UL << (pin)) 59 | #define digitalPinToTimer(pin) (0) 60 | #define digitalPinToInterrupt(pin) (pin) 61 | #define NOT_AN_INTERRUPT (-1) 62 | #define portOutputRegister(port) ((volatile uint32_t*) sio_hw->gpio_out) 63 | #define portInputRegister(port) ((volatile uint32_t*) sio_hw->gpio_in) 64 | #define portModeRegister(port) ((volatile uint32_t*) sio_hw->gpio_oe) 65 | 66 | // IO config 67 | void pinMode(pin_size_t pinNumber, PinMode pinMode); 68 | 69 | // SIO (GPIO) 70 | void digitalWrite(pin_size_t pinNumber, PinStatus status); 71 | PinStatus digitalRead(pin_size_t pinNumber); 72 | 73 | // ADC 74 | int analogRead(pin_size_t pinNumber); 75 | float analogReadTemp(); // Returns core temp in Centigrade 76 | 77 | // PWM 78 | void analogWrite(pin_size_t pinNumber, int value); 79 | void analogWriteFreq(uint32_t freq); 80 | void analogWriteRange(uint32_t range); 81 | void analogWriteResolution(int res); 82 | 83 | // Timing 84 | void delay(unsigned long); 85 | void delayMicroseconds(unsigned int us); 86 | unsigned long millis(); 87 | 88 | #ifdef __cplusplus 89 | } // extern "C" 90 | #endif 91 | 92 | // Ancient AVR defines 93 | #define HAVE_HWSERIAL0 94 | #define HAVE_HWSERIAL1 95 | #define HAVE_HWSERIAL2 96 | 97 | #ifdef __cplusplus 98 | #include "SerialUSB.h" 99 | #include "SerialUART.h" 100 | #include "RP2040.h" 101 | #include "Bootsel.h" 102 | 103 | // Template which will evaluate at *compile time* to a single 32b number 104 | // with the specified bits set. 105 | template 106 | constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) { 107 | return i < N ? (1L << a[i]) | __bitset(a, i+1) : 0; 108 | } 109 | #endif 110 | 111 | 112 | // ARM toolchain doesn't provide itoa etc, provide them 113 | #include "api/itoa.h" 114 | 115 | #endif // Arduino_h 116 | -------------------------------------------------------------------------------- /Packages_Patches/rp2040/hardware/rp2040/1.3.1/platform.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Earle F. Philhower, III 2 | # 3 | # Raspberry Pi RP2040 Core platform file 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | # See the GNU Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | # For more info: 20 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification 21 | 22 | name=Raspberry Pi RP2040 Boards(1.3.1) 23 | version=1.3.1 24 | 25 | 26 | 27 | 28 | 29 | 30 | compiler.path={runtime.tools.pqt-gcc.path}/bin/ 31 | 32 | # Compile variables 33 | # ----------------- 34 | 35 | compiler.warning_flags=-w 36 | compiler.warning_flags.none=-w 37 | compiler.warning_flags.default= 38 | compiler.warning_flags.more=-Wall 39 | compiler.warning_flags.all=-Wall -Wextra 40 | 41 | compiler.defines={build.led} 42 | compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" 43 | compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections -fno-exceptions 44 | compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt" 45 | 46 | compiler.c.cmd=arm-none-eabi-gcc 47 | compiler.c.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -std=gnu17 -g 48 | compiler.c.elf.cmd=arm-none-eabi-g++ 49 | compiler.c.elf.flags={compiler.defines} {compiler.flags} -Wl,--gc-sections -u _printf_float -u _scanf_float 50 | compiler.S.cmd=arm-none-eabi-gcc 51 | compiler.S.flags=-c -g -x assembler-with-cpp -MMD {compiler.includes} -g 52 | compiler.cpp.cmd=arm-none-eabi-g++ 53 | compiler.cpp.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -fno-rtti -std=gnu++17 -g 54 | 55 | compiler.ar.cmd=arm-none-eabi-ar 56 | compiler.ar.flags=rcs 57 | compiler.objcopy.cmd=arm-none-eabi-objcopy 58 | compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 59 | compiler.elf2hex.bin.flags=-O binary 60 | compiler.elf2hex.hex.flags=-O ihex -R .eeprom 61 | compiler.elf2hex.cmd=arm-none-eabi-objcopy 62 | compiler.ldflags={compiler.wrap} -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common 63 | compiler.size.cmd=arm-none-eabi-size 64 | compiler.define=-DARDUINO= 65 | compiler.readelf.cmd=arm-none-eabi-readelf 66 | 67 | # this can be overriden in boards.txt 68 | build.extra_flags= 69 | 70 | # These can be overridden in platform.local.txt 71 | compiler.c.extra_flags= 72 | compiler.c.elf.extra_flags= 73 | compiler.cpp.extra_flags= 74 | compiler.S.extra_flags= 75 | compiler.ar.extra_flags= 76 | compiler.elf2hex.extra_flags= 77 | 78 | # Board configuration, set in boards.txt. Present here to ensure substitution works 79 | build.flash_length= 80 | build.eeprom_start= 81 | build.fs_start= 82 | build.fs_end= 83 | 84 | build.boot2=boot2_generic_03h_4_padded_checksum 85 | 86 | # Allow Pico boards do be auto-discovered by the IDE 87 | discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/discovery.py" 88 | 89 | 90 | # Compile patterns 91 | # ---------------- 92 | 93 | ## Compile c files 94 | ## Add -DBOARD_NAME="{build.board}" 95 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 96 | 97 | ## Compile c++ files 98 | ## Add -DBOARD_NAME="{build.board}" 99 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 100 | 101 | ## Compile S files 102 | ## Add -DBOARD_NAME="{build.board}" 103 | recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 104 | 105 | ## Create archives 106 | # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value 107 | archive_file_path={build.path}/{archive_file} 108 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" 109 | 110 | ## Combine gc-sections, archives, and objects 111 | recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/simplesub.py" --input "{runtime.platform.path}/lib/memmap_default.ld" --out "{build.path}/memmap_default.ld" --sub __FLASH_LENGTH__ {build.flash_length} --sub __EEPROM_START__ {build.eeprom_start} --sub __FS_START__ {build.fs_start} --sub __FS_END__ {build.fs_end} 112 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nosys.specs -Wl,--start-group {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "{runtime.platform.path}/lib/libpico.a" -lm "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "{runtime.platform.path}/assembly/{build.boot2}.S" -lc -lstdc++ -Wl,--end-group 113 | 114 | ## Create output (UF2 file) 115 | recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" 116 | 117 | build.preferred_out_format=uf2 118 | 119 | ## Save hex 120 | recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} 121 | recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} 122 | 123 | ## Compute size 124 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" 125 | recipe.size.regex=^(?:\.boot2|\.text|\.rodata|\.ARM\.extab|\.ARM\.exidx)\s+([0-9]+).* 126 | recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_data)\s+([0-9]+).* 127 | 128 | tools.uf2conv.path= 129 | # Because the variable expansion doesn't allow one tool to find another, the following lines 130 | # will point to "{runtime.platform.path}/tools/python3/python3" in GIT and 131 | # "{runtime.tools.pqt-python3.path}/python3" for JSON board manager releases. 132 | tools.uf2conv.cmd={runtime.tools.pqt-python3.path}/python3 133 | 134 | tools.uf2conv.upload.protocol=uf2 135 | tools.uf2conv.upload.params.verbose= 136 | tools.uf2conv.upload.params.quiet= 137 | tools.uf2conv.upload.pattern="{cmd}" "{runtime.platform.path}/tools/uf2conv.py" --serial "{serial.port}" --family RP2040 --deploy "{build.path}/{build.project_name}.uf2" 138 | 139 | 140 | tools.picoprobe.cmd={runtime.tools.pqt-openocd.path} 141 | 142 | tools.picoprobe.upload.protocol=picoprobe 143 | tools.picoprobe.upload.params.verbose= 144 | tools.picoprobe.upload.params.quiet= 145 | tools.picoprobe.upload.pattern="{cmd}/bin/openocd" -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "program {build.path}/{build.project_name}.elf verify reset exit" 146 | -------------------------------------------------------------------------------- /Packages_Patches/rp2040/hardware/rp2040/1.4.0/cores/rp2040/Arduino.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Arduino header for the Raspberry Pi Pico RP2040 3 | * 4 | * Copyright (c) 2021 Earle F. Philhower, III 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef Arduino_h 22 | #define Arduino_h 23 | 24 | #include 25 | #include 26 | #include 27 | // Wacky deprecated AVR compatibilty functions 28 | #include "stdlib_noniso.h" 29 | 30 | #include "api/ArduinoAPI.h" 31 | #include 32 | 33 | 34 | // Required for the port*Register macros 35 | #include "hardware/gpio.h" 36 | 37 | #include "debug_internal.h" 38 | 39 | #ifdef __cplusplus 40 | extern "C"{ 41 | #endif // __cplusplus 42 | 43 | // For compatibility to many platforms and libraries 44 | #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) 45 | #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) 46 | #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) 47 | 48 | // Disable/reenable all interrupts. Safely handles nested disables 49 | void interrupts(); 50 | void noInterrupts(); 51 | 52 | // GPIO change/value interrupts 53 | void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode); 54 | void detachInterrupt(pin_size_t pin); 55 | 56 | // AVR compatibilty macros...naughty and accesses the HW directly 57 | #define digitalPinToPort(pin) (0) 58 | #define digitalPinToBitMask(pin) (1UL << (pin)) 59 | #define digitalPinToTimer(pin) (0) 60 | #define digitalPinToInterrupt(pin) (pin) 61 | #define NOT_AN_INTERRUPT (-1) 62 | #define portOutputRegister(port) ((volatile uint32_t*) sio_hw->gpio_out) 63 | #define portInputRegister(port) ((volatile uint32_t*) sio_hw->gpio_in) 64 | #define portModeRegister(port) ((volatile uint32_t*) sio_hw->gpio_oe) 65 | 66 | // IO config 67 | void pinMode(pin_size_t pinNumber, PinMode pinMode); 68 | 69 | // SIO (GPIO) 70 | void digitalWrite(pin_size_t pinNumber, PinStatus status); 71 | PinStatus digitalRead(pin_size_t pinNumber); 72 | 73 | // ADC 74 | int analogRead(pin_size_t pinNumber); 75 | float analogReadTemp(); // Returns core temp in Centigrade 76 | 77 | // PWM 78 | void analogWrite(pin_size_t pinNumber, int value); 79 | void analogWriteFreq(uint32_t freq); 80 | void analogWriteRange(uint32_t range); 81 | void analogWriteResolution(int res); 82 | 83 | // Timing 84 | void delay(unsigned long); 85 | void delayMicroseconds(unsigned int us); 86 | unsigned long millis(); 87 | 88 | #ifdef __cplusplus 89 | } // extern "C" 90 | #endif 91 | 92 | // Ancient AVR defines 93 | #define HAVE_HWSERIAL0 94 | #define HAVE_HWSERIAL1 95 | #define HAVE_HWSERIAL2 96 | 97 | #ifdef __cplusplus 98 | #include "SerialUSB.h" 99 | #include "SerialUART.h" 100 | #include "RP2040.h" 101 | #include "Bootsel.h" 102 | 103 | // Template which will evaluate at *compile time* to a single 32b number 104 | // with the specified bits set. 105 | template 106 | constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) { 107 | return i < N ? (1L << a[i]) | __bitset(a, i+1) : 0; 108 | } 109 | #endif 110 | 111 | 112 | // ARM toolchain doesn't provide itoa etc, provide them 113 | #include "api/itoa.h" 114 | 115 | #endif // Arduino_h 116 | -------------------------------------------------------------------------------- /Packages_Patches/rp2040/hardware/rp2040/1.4.0/platform.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Earle F. Philhower, III 2 | # 3 | # Raspberry Pi RP2040 Core platform file 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | # See the GNU Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | # For more info: 20 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification 21 | 22 | name=Raspberry Pi RP2040 Boards(1.4.0) 23 | version=1.4.0 24 | 25 | 26 | 27 | 28 | 29 | 30 | compiler.path={runtime.tools.pqt-gcc.path}/bin/ 31 | 32 | # Compile variables 33 | # ----------------- 34 | 35 | compiler.warning_flags=-w 36 | compiler.warning_flags.none=-w 37 | compiler.warning_flags.default= 38 | compiler.warning_flags.more=-Wall 39 | compiler.warning_flags.all=-Wall -Wextra 40 | 41 | compiler.defines={build.led} 42 | compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" 43 | compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections -fno-exceptions 44 | compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt" 45 | 46 | compiler.c.cmd=arm-none-eabi-gcc 47 | compiler.c.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -std=gnu17 -g 48 | compiler.c.elf.cmd=arm-none-eabi-g++ 49 | compiler.c.elf.flags={compiler.defines} {compiler.flags} -Wl,--gc-sections -u _printf_float -u _scanf_float 50 | compiler.S.cmd=arm-none-eabi-gcc 51 | compiler.S.flags=-c -g -x assembler-with-cpp -MMD {compiler.includes} -g 52 | compiler.cpp.cmd=arm-none-eabi-g++ 53 | compiler.cpp.flags=-c {compiler.defines} {compiler.flags} {compiler.includes} -fno-rtti -std=gnu++17 -g 54 | 55 | compiler.ar.cmd=arm-none-eabi-ar 56 | compiler.ar.flags=rcs 57 | compiler.objcopy.cmd=arm-none-eabi-objcopy 58 | compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 59 | compiler.elf2hex.bin.flags=-O binary 60 | compiler.elf2hex.hex.flags=-O ihex -R .eeprom 61 | compiler.elf2hex.cmd=arm-none-eabi-objcopy 62 | compiler.ldflags={compiler.wrap} -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common 63 | compiler.size.cmd=arm-none-eabi-size 64 | compiler.define=-DARDUINO= 65 | compiler.readelf.cmd=arm-none-eabi-readelf 66 | 67 | # this can be overriden in boards.txt 68 | build.extra_flags= 69 | 70 | # These can be overridden in platform.local.txt 71 | compiler.c.extra_flags= 72 | compiler.c.elf.extra_flags= 73 | compiler.cpp.extra_flags= 74 | compiler.S.extra_flags= 75 | compiler.ar.extra_flags= 76 | compiler.elf2hex.extra_flags= 77 | 78 | # Board configuration, set in boards.txt. Present here to ensure substitution works 79 | build.flash_length= 80 | build.eeprom_start= 81 | build.fs_start= 82 | build.fs_end= 83 | 84 | build.boot2=boot2_generic_03h_4_padded_checksum 85 | 86 | # Allow Pico boards do be auto-discovered by the IDE 87 | discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/discovery.py" 88 | 89 | 90 | # Compile patterns 91 | # ---------------- 92 | 93 | ## Compile c files 94 | ## Add -DBOARD_NAME="{build.board}" 95 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 96 | 97 | ## Compile c++ files 98 | ## Add -DBOARD_NAME="{build.board}" 99 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 100 | 101 | ## Compile S files 102 | ## Add -DBOARD_NAME="{build.board}" 103 | recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.usbpid} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DBOARD_NAME="{build.board}" -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.debug_port} {build.debug_level} {includes} "{source_file}" -o "{object_file}" 104 | 105 | ## Create archives 106 | # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value 107 | archive_file_path={build.path}/{archive_file} 108 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" 109 | 110 | ## Combine gc-sections, archives, and objects 111 | recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3" "{runtime.platform.path}/tools/simplesub.py" --input "{runtime.platform.path}/lib/memmap_default.ld" --out "{build.path}/memmap_default.ld" --sub __FLASH_LENGTH__ {build.flash_length} --sub __EEPROM_START__ {build.eeprom_start} --sub __FS_START__ {build.fs_start} --sub __FS_END__ {build.fs_end} 112 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nosys.specs -Wl,--as-needed -Wl,--start-group {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" -Wl,--whole-archive "{runtime.platform.path}/lib/libpico.a" -Wl,--no-whole-archive -lm "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "{runtime.platform.path}/assembly/{build.boot2}.S" -lc -lstdc++ -Wl,--end-group 113 | 114 | ## Create output (UF2 file) 115 | recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" 116 | 117 | build.preferred_out_format=uf2 118 | 119 | ## Save hex 120 | recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} 121 | recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} 122 | 123 | ## Compute size 124 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" 125 | recipe.size.regex=^(?:\.boot2|\.text|\.rodata|\.ARM\.extab|\.ARM\.exidx)\s+([0-9]+).* 126 | recipe.size.regex.data=^(?:\.data|\.bss|\.ram_vector_table|\.uninitialized_data)\s+([0-9]+).* 127 | 128 | tools.uf2conv.path= 129 | # Because the variable expansion doesn't allow one tool to find another, the following lines 130 | # will point to "{runtime.platform.path}/tools/python3/python3" in GIT and 131 | # "{runtime.tools.pqt-python3.path}/python3" for JSON board manager releases. 132 | tools.uf2conv.cmd={runtime.tools.pqt-python3.path}/python3 133 | 134 | tools.uf2conv.upload.protocol=uf2 135 | tools.uf2conv.upload.params.verbose= 136 | tools.uf2conv.upload.params.quiet= 137 | tools.uf2conv.upload.pattern="{cmd}" "{runtime.platform.path}/tools/uf2conv.py" --serial "{serial.port}" --family RP2040 --deploy "{build.path}/{build.project_name}.uf2" 138 | 139 | 140 | tools.picoprobe.cmd={runtime.tools.pqt-openocd.path} 141 | 142 | tools.picoprobe.upload.protocol=picoprobe 143 | tools.picoprobe.upload.params.verbose= 144 | tools.picoprobe.upload.params.quiet= 145 | tools.picoprobe.upload.pattern="{cmd}/bin/openocd" -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -s "{cmd}/share/openocd/scripts" -c "program {build.path}/{build.project_name}.elf verify reset exit" 146 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # RPI_PICO_TimerInterrupt Library 2 | 3 | [![arduino-library-badge](https://www.ardu-badge.com/badge/RPI_PICO_TimerInterrupt.svg?)](https://www.ardu-badge.com/RPI_PICO_TimerInterrupt) 4 | [![GitHub release](https://img.shields.io/github/release/khoih-prog/RPI_PICO_TimerInterrupt.svg)](https://github.com/khoih-prog/RPI_PICO_TimerInterrupt/releases) 5 | [![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/RPI_PICO_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/RPI_PICO_TimerInterrupt.svg)](http://github.com/khoih-prog/RPI_PICO_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.3.1](#releases-v131) 21 | * [Releases v1.3.0](#releases-v130) 22 | * [Releases v1.2.0](#releases-v120) 23 | * [Releases v1.1.1](#releases-v111) 24 | * [Releases v1.1.0](#releases-v110) 25 | * [Releases v1.0.1](#releases-v101) 26 | * [Initial Releases v1.0.0](#initial-releases-v100) 27 | 28 | 29 | --- 30 | --- 31 | 32 | ## Changelog 33 | 34 | ### Releases v1.3.1 35 | 36 | 1. Using `float` instead of `ulong` for better interval accuracy 37 | 38 | ### Releases v1.3.0 39 | 40 | 1. Fix severe bug affecting time between the starts. Check [Enable fixed timing between timer calls (vs fixed time btw. end of timer call and next call as implemented) #3](https://github.com/khoih-prog/RPI_PICO_TimerInterrupt/issues/3) 41 | 42 | 43 | ### Releases v1.2.0 44 | 45 | 1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories 46 | 2. Add example [multiFileProject](examples/multiFileProject) to demo for multiple-file project. 47 | 3. Optimize library code by using `reference-passing` instead of `value-passing` 48 | 4. Update all examples 49 | 50 | ### Releases v1.1.1 51 | 52 | 1. Fix platform in `library.json` 53 | 54 | ### Releases v1.1.0 55 | 56 | 1. Add support to new boards (**ADAFRUIT_ITSYBITSY_RP2040, ADAFRUIT_QTPY_RP2040, ADAFRUIT_STEMMAFRIEND_RP2040, ADAFRUIT_TRINKEYQT_RP2040, ADAFRUIT_MACROPAD_RP2040, SPARKFUN_PROMICRO_RP2040, etc.**) using the arduino-pico core 57 | 2. Add `ISR_16_Timers_Array_Complex` examples. 58 | 3. Fix examples' bug 59 | 60 | ### Releases v1.0.1 61 | 62 | 1. Update README and Packages' Patches to match core arduino-pico core v1.4.0 63 | 64 | ### Initial Releases v1.0.0 65 | 66 | 1. Initial coding to support RP2040-based boards such as **RASPBERRY_PI_PICO**, etc. using [**Earle Philhower's arduino-pico** core](https://github.com/earlephilhower/arduino-pico) 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/Argument_Complex/Argument_Complex.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Argument_Complex.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | 23 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 24 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 25 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 26 | #define TIMER_INTERRUPT_DEBUG 1 27 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 28 | 29 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 30 | #include "RPi_Pico_TimerInterrupt.h" 31 | 32 | #if !defined(LED_BUILTIN) 33 | #define LED_BUILTIN 25 34 | #endif 35 | 36 | // Init RPI_PICO_Timer 37 | RPI_PICO_Timer ITimer1(1); 38 | 39 | struct pinStruct 40 | { 41 | unsigned int Pin1; 42 | unsigned int Pin2; 43 | unsigned int Pin3; 44 | }; 45 | 46 | volatile pinStruct myOutputPins = { LED_BUILTIN, 0, 1 }; 47 | 48 | bool TimerHandler(struct repeating_timer *t) 49 | { 50 | (void) t; 51 | 52 | static bool toggle = false; 53 | 54 | //timer interrupt toggles pins 55 | #if (TIMER_INTERRUPT_DEBUG > 0) 56 | Serial.print("Toggle pin1 = "); Serial.println( myOutputPins.Pin1 ); 57 | #endif 58 | 59 | digitalWrite(myOutputPins.Pin1, toggle); 60 | 61 | #if (TIMER_INTERRUPT_DEBUG > 0) 62 | Serial.print("Read pin2 ("); Serial.print( myOutputPins.Pin2 ); 63 | Serial.print(") = "); 64 | Serial.println(digitalRead(myOutputPins.Pin2) ? "HIGH" : "LOW" ); 65 | 66 | Serial.print("Read pin3 ("); Serial.print( myOutputPins.Pin1 ); 67 | Serial.print(") = "); 68 | Serial.println(digitalRead(myOutputPins.Pin3) ? "HIGH" : "LOW" ); 69 | #endif 70 | 71 | toggle = !toggle; 72 | 73 | return true; 74 | } 75 | 76 | #define TIMER_INTERVAL_MS 1000 77 | 78 | void setup() 79 | { 80 | pinMode(myOutputPins.Pin1, OUTPUT); 81 | pinMode(myOutputPins.Pin2, OUTPUT); 82 | pinMode(myOutputPins.Pin3, OUTPUT); 83 | 84 | Serial.begin(115200); 85 | while (!Serial); 86 | 87 | Serial.print(F("\nStarting Argument_Complex on ")); Serial.println(BOARD_NAME); 88 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 89 | //Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 90 | 91 | // Interval in microsecs 92 | if (ITimer1.attachInterruptInterval(TIMER_INTERVAL_MS * 1000, TimerHandler)) 93 | { 94 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 95 | } 96 | else 97 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 98 | } 99 | 100 | void loop() 101 | { 102 | } 103 | -------------------------------------------------------------------------------- /examples/Argument_None/Argument_None.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Argument_None.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | 23 | /* 24 | Notes: 25 | Special design is necessary to share data between interrupt code and the rest of your program. 26 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 27 | variable can not spontaneously change. Because your function may change variables while your program is using them, 28 | the compiler needs this hint. But volatile alone is often not enough. 29 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 30 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 31 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 32 | or the entire sequence of your code which accesses the data. 33 | */ 34 | 35 | 36 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 37 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 38 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 39 | #define TIMER_INTERRUPT_DEBUG 1 40 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 41 | 42 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 43 | #include "RPi_Pico_TimerInterrupt.h" 44 | 45 | #ifndef LED_BUILTIN 46 | #define LED_BUILTIN 25 47 | #endif 48 | 49 | #define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of RPI_PICO 50 | 51 | bool TimerHandler0(struct repeating_timer *t) 52 | { 53 | (void) t; 54 | 55 | static bool toggle0 = false; 56 | 57 | #if (TIMER_INTERRUPT_DEBUG > 0) 58 | Serial.print("ITimer0: millis() = "); Serial.println(millis()); 59 | #endif 60 | 61 | //timer interrupt toggles pin LED_BUILTIN 62 | digitalWrite(LED_BUILTIN, toggle0); 63 | toggle0 = !toggle0; 64 | 65 | return true; 66 | } 67 | 68 | bool TimerHandler1(struct repeating_timer *t) 69 | { 70 | (void) t; 71 | 72 | static bool toggle1 = false; 73 | 74 | #if (TIMER_INTERRUPT_DEBUG > 0) 75 | Serial.print("ITimer1: millis() = "); Serial.println(millis()); 76 | #endif 77 | 78 | //timer interrupt toggles outputPin 79 | digitalWrite(PIN_D1, toggle1); 80 | toggle1 = !toggle1; 81 | 82 | return true; 83 | } 84 | 85 | #define TIMER0_INTERVAL_MS 1000 86 | 87 | #define TIMER1_INTERVAL_MS 5000 88 | 89 | // Init RPI_PICO_Timer 90 | RPI_PICO_Timer ITimer0(0); 91 | RPI_PICO_Timer ITimer1(1); 92 | 93 | void setup() 94 | { 95 | pinMode(LED_BUILTIN, OUTPUT); 96 | pinMode(PIN_D1, OUTPUT); 97 | 98 | Serial.begin(115200); 99 | while (!Serial); 100 | 101 | delay(100); 102 | 103 | Serial.print(F("\nStarting Argument_None on ")); Serial.println(BOARD_NAME); 104 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 105 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 106 | 107 | // Interval in microsecs 108 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 109 | { 110 | Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis()); 111 | } 112 | else 113 | Serial.println(F("Can't set ITimer0. Select another Timer, freq. or timer")); 114 | 115 | 116 | // Interval in microsecs 117 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 118 | { 119 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 120 | } 121 | else 122 | Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer")); 123 | } 124 | 125 | void loop() 126 | { 127 | 128 | } 129 | -------------------------------------------------------------------------------- /examples/Argument_Simple/Argument_Simple.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Argument_Simple.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | 23 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 24 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 25 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 26 | #define TIMER_INTERRUPT_DEBUG 1 27 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 28 | 29 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 30 | #include "RPi_Pico_TimerInterrupt.h" 31 | 32 | #if !defined(LED_BUILTIN) 33 | #define LED_BUILTIN 25 34 | #endif 35 | 36 | unsigned int outputPin1 = LED_BUILTIN; 37 | unsigned int outputPin2 = 1; 38 | 39 | // Init RPI_PICO_Timer 40 | RPI_PICO_Timer ITimer1(1); 41 | RPI_PICO_Timer ITimer2(2); 42 | 43 | #define TIMER1_INTERVAL_MS 1000 44 | 45 | bool TimerHandler1(struct repeating_timer *t) 46 | { 47 | (void) t; 48 | 49 | static bool toggle1 = false; 50 | 51 | #if (TIMER_INTERRUPT_DEBUG > 0) 52 | //timer interrupt toggles pin outputPin1 53 | Serial.print("Pin"); Serial.print(outputPin1); Serial.println(toggle1 ? F(" ON") : F(" OFF")); 54 | #endif 55 | 56 | digitalWrite(outputPin1, toggle1); 57 | toggle1 = !toggle1; 58 | 59 | return true; 60 | } 61 | 62 | #define TIMER2_INTERVAL_MS 2000 63 | 64 | bool TimerHandler2(struct repeating_timer *t) 65 | { 66 | (void) t; 67 | 68 | static bool toggle2 = false; 69 | 70 | #if (TIMER_INTERRUPT_DEBUG > 0) 71 | //timer interrupt toggles pin outputPin2 72 | Serial.print("Pin"); Serial.print(outputPin2); Serial.println(toggle2 ? F(" ON") : F(" OFF")); 73 | #endif 74 | 75 | //timer interrupt toggles pin outputPin2 76 | digitalWrite(outputPin2, toggle2); 77 | toggle2 = !toggle2; 78 | 79 | return true; 80 | } 81 | 82 | void setup() 83 | { 84 | pinMode(outputPin1, OUTPUT); 85 | pinMode(outputPin2, OUTPUT); 86 | 87 | Serial.begin(115200); 88 | while (!Serial); 89 | 90 | Serial.print(F("\nStarting Argument_Simple on ")); Serial.println(BOARD_NAME); 91 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 92 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 93 | 94 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 95 | { 96 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 97 | 98 | #if (TIMER_INTERRUPT_DEBUG > 1) 99 | Serial.print(F("OutputPin1 = ")); Serial.print(outputPin1); 100 | #endif 101 | } 102 | else 103 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 104 | 105 | 106 | if (ITimer2.attachInterruptInterval(TIMER2_INTERVAL_MS * 1000, TimerHandler2)) 107 | { 108 | Serial.print(F("Starting ITimer2 OK, millis() = ")); Serial.println(millis()); 109 | 110 | #if (TIMER_INTERRUPT_DEBUG > 1) 111 | Serial.print(F("OutputPin2 = ")); Serial.print(outputPin2); 112 | #endif 113 | } 114 | else 115 | Serial.println(F("Can't set ITimer2. Select another freq. or timer")); 116 | } 117 | 118 | void loop() 119 | { 120 | } 121 | -------------------------------------------------------------------------------- /examples/Change_Interval/Change_Interval.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | Change_Interval.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | 23 | /* 24 | Notes: 25 | Special design is necessary to share data between interrupt code and the rest of your program. 26 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 27 | variable can not spontaneously change. Because your function may change variables while your program is using them, 28 | the compiler needs this hint. But volatile alone is often not enough. 29 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 30 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 31 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 32 | or the entire sequence of your code which accesses the data. 33 | */ 34 | 35 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 36 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 37 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 38 | #define TIMER_INTERRUPT_DEBUG 1 39 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 40 | 41 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 42 | #include "RPi_Pico_TimerInterrupt.h" 43 | 44 | #ifndef LED_BUILTIN 45 | #define LED_BUILTIN 25 46 | #endif 47 | 48 | #define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of RPI_PICO 49 | 50 | volatile uint32_t Timer0Count = 0; 51 | volatile uint32_t Timer1Count = 0; 52 | 53 | bool TimerHandler0(struct repeating_timer *t) 54 | { 55 | (void) t; 56 | 57 | static bool toggle0 = false; 58 | 59 | // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR 60 | Timer0Count++; 61 | 62 | #if (TIMER_INTERRUPT_DEBUG > 0) 63 | Serial.print("ITimer0: millis() = "); Serial.println(millis()); 64 | #endif 65 | 66 | //timer interrupt toggles pin LED_BUILTIN 67 | digitalWrite(LED_BUILTIN, toggle0); 68 | toggle0 = !toggle0; 69 | 70 | return true; 71 | } 72 | 73 | bool TimerHandler1(struct repeating_timer *t) 74 | { 75 | (void) t; 76 | 77 | static bool toggle1 = false; 78 | 79 | // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR 80 | Timer1Count++; 81 | 82 | #if (TIMER_INTERRUPT_DEBUG > 0) 83 | Serial.print("ITimer1: millis() = "); Serial.println(millis()); 84 | #endif 85 | 86 | //timer interrupt toggles PIN_D1 87 | digitalWrite(PIN_D1, toggle1); 88 | toggle1 = !toggle1; 89 | 90 | return true; 91 | } 92 | 93 | void printResult(uint32_t currTime) 94 | { 95 | Serial.print(F("Time = ")); Serial.print(currTime); 96 | Serial.print(F(", Timer0Count = ")); Serial.print(Timer0Count); 97 | Serial.print(F(", Timer1Count = ")); Serial.println(Timer1Count); 98 | } 99 | 100 | #define TIMER0_INTERVAL_MS 2000 101 | 102 | #define TIMER1_INTERVAL_MS 5000 103 | 104 | // Init ESP32 timer 0 105 | RPI_PICO_Timer ITimer0(0); 106 | RPI_PICO_Timer ITimer1(1); 107 | 108 | void setup() 109 | { 110 | pinMode(LED_BUILTIN, OUTPUT); 111 | pinMode(PIN_D1, OUTPUT); 112 | 113 | Serial.begin(115200); 114 | while (!Serial); 115 | 116 | delay(100); 117 | 118 | Serial.print(F("\nStarting Change_Interval on ")); Serial.println(BOARD_NAME); 119 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 120 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 121 | 122 | // Interval in microsecs 123 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 124 | { 125 | Serial.print(F("Starting ITimer0 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_Complex/ISR_16_Timers_Array_Complex.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | ISR_16_Timers_Array.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | /* 23 | Notes: 24 | Special design is necessary to share data between interrupt code and the rest of your program. 25 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 26 | variable can not spontaneously change. Because your function may change variables while your program is using them, 27 | the compiler needs this hint. But volatile alone is often not enough. 28 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 29 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 30 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 31 | or the entire sequence of your code which accesses the data. 32 | 33 | This example will demonstrate the nearly perfect accuracy compared to software timers by printing the actual elapsed millisecs. 34 | Being ISR-based timers, their executions are not blocked by bad-behaving functions / tasks, such as connecting to WiFi, Internet 35 | and Blynk services. You can also have many (up to 16) timers to use. 36 | This non-being-blocked important feature is absolutely necessary for mission-critical tasks. 37 | You'll see blynkTimer is blocked while connecting to WiFi / Internet / Blynk, and elapsed time is very unaccurate 38 | In this super simple example, you don't see much different after Blynk is connected, because of no competing task is 39 | written 40 | */ 41 | 42 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 43 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 44 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 45 | 46 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 47 | #include "RPi_Pico_TimerInterrupt.h" 48 | 49 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 50 | #include "RPi_Pico_ISR_Timer.h" 51 | 52 | #include // https://github.com/jfturcot/SimpleTimer 53 | 54 | #ifndef LED_BUILTIN 55 | #define LED_BUILTIN 25 56 | #endif 57 | 58 | #ifndef LED_BLUE 59 | #define LED_BLUE 10 60 | #endif 61 | 62 | #ifndef LED_RED 63 | #define LED_RED 11 64 | #endif 65 | 66 | #define HW_TIMER_INTERVAL_US 10000L 67 | 68 | volatile uint32_t startMillis = 0; 69 | 70 | // You can select RPI_PICO_Timer from 0 to 3 71 | // Init RPI_PICO_Timer 72 | RPI_PICO_Timer ITimer(1); 73 | 74 | // Init RPI_PICO_ISR_Timer 75 | // Each RPI_PICO_ISR_Timer can service 16 different ISR-based timers 76 | RPI_PICO_ISR_Timer ISR_Timer; 77 | 78 | #define LED_TOGGLE_INTERVAL_MS 2000L 79 | 80 | // Never use Serial.print inside this ISR. Will hang the system 81 | bool TimerHandler(struct repeating_timer *t) 82 | { 83 | (void) t; 84 | 85 | static bool toggle = false; 86 | static int timeRun = 0; 87 | 88 | ISR_Timer.run(); 89 | 90 | // Toggle LED every LED_TOGGLE_INTERVAL_MS = 2000ms = 2s 91 | if (++timeRun == ((LED_TOGGLE_INTERVAL_MS * 1000) / HW_TIMER_INTERVAL_US) ) 92 | { 93 | timeRun = 0; 94 | 95 | //timer interrupt toggles pin LED_BUILTIN 96 | digitalWrite(LED_BUILTIN, toggle); 97 | toggle = !toggle; 98 | } 99 | 100 | return true; 101 | } 102 | 103 | ///////////////////////////////////////////////// 104 | 105 | #define NUMBER_ISR_TIMERS 16 106 | 107 | typedef void (*irqCallback) (); 108 | 109 | ///////////////////////////////////////////////// 110 | 111 | #define USE_COMPLEX_STRUCT true 112 | 113 | #if USE_COMPLEX_STRUCT 114 | 115 | typedef struct 116 | { 117 | irqCallback irqCallbackFunc; 118 | uint32_t TimerInterval; 119 | unsigned long deltaMillis; 120 | unsigned long previousMillis; 121 | } ISRTimerData; 122 | 123 | // In RP2040, avoid doing something fancy in ISR, for example Serial.print() 124 | // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment 125 | // Or you can get this run-time error / crash 126 | 127 | void doingSomething(int index); 128 | 129 | #else 130 | 131 | volatile unsigned long deltaMillis [NUMBER_ISR_TIMERS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 132 | volatile unsigned long previousMillis [NUMBER_ISR_TIMERS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 133 | 134 | // You can assign any interval for any timer here, in milliseconds 135 | uint32_t TimerInterval[NUMBER_ISR_TIMERS] = 136 | { 137 | 5000L, 10000L, 15000L, 20000L, 25000L, 30000L, 35000L, 40000L, 138 | 45000L, 50000L, 55000L, 60000L, 65000L, 70000L, 75000L, 80000L 139 | }; 140 | 141 | void doingSomething(int index) 142 | { 143 | unsigned long currentMillis = millis(); 144 | 145 | deltaMillis[index] = currentMillis - previousMillis[index]; 146 | previousMillis[index] = currentMillis; 147 | } 148 | 149 | #endif 150 | 151 | //////////////////////////////////// 152 | // Shared 153 | //////////////////////////////////// 154 | 155 | void doingSomething0() 156 | { 157 | doingSomething(0); 158 | } 159 | 160 | void doingSomething1() 161 | { 162 | doingSomething(1); 163 | } 164 | 165 | void doingSomething2() 166 | { 167 | doingSomething(2); 168 | } 169 | 170 | void doingSomething3() 171 | { 172 | doingSomething(3); 173 | } 174 | 175 | void doingSomething4() 176 | { 177 | doingSomething(4); 178 | } 179 | 180 | void doingSomething5() 181 | { 182 | doingSomething(5); 183 | } 184 | 185 | void doingSomething6() 186 | { 187 | doingSomething(6); 188 | } 189 | 190 | void doingSomething7() 191 | { 192 | doingSomething(7); 193 | } 194 | 195 | void doingSomething8() 196 | { 197 | doingSomething(8); 198 | } 199 | 200 | void doingSomething9() 201 | { 202 | doingSomething(9); 203 | } 204 | 205 | void doingSomething10() 206 | { 207 | doingSomething(10); 208 | } 209 | 210 | void doingSomething11() 211 | { 212 | doingSomething(11); 213 | } 214 | 215 | void doingSomething12() 216 | { 217 | doingSomething(12); 218 | } 219 | 220 | void doingSomething13() 221 | { 222 | doingSomething(13); 223 | } 224 | 225 | void doingSomething14() 226 | { 227 | doingSomething(14); 228 | } 229 | 230 | void doingSomething15() 231 | { 232 | doingSomething(15); 233 | } 234 | 235 | #if USE_COMPLEX_STRUCT 236 | 237 | ISRTimerData curISRTimerData[NUMBER_ISR_TIMERS] = 238 | { 239 | //irqCallbackFunc, TimerInterval, deltaMillis, previousMillis 240 | { doingSomething0, 5000L, 0, 0 }, 241 | { doingSomething1, 10000L, 0, 0 }, 242 | { doingSomething2, 15000L, 0, 0 }, 243 | { doingSomething3, 20000L, 0, 0 }, 244 | { doingSomething4, 25000L, 0, 0 }, 245 | { doingSomething5, 30000L, 0, 0 }, 246 | { doingSomething6, 35000L, 0, 0 }, 247 | { doingSomething7, 40000L, 0, 0 }, 248 | { doingSomething8, 45000L, 0, 0 }, 249 | { doingSomething9, 50000L, 0, 0 }, 250 | { doingSomething10, 55000L, 0, 0 }, 251 | { doingSomething11, 60000L, 0, 0 }, 252 | { doingSomething12, 65000L, 0, 0 }, 253 | { doingSomething13, 70000L, 0, 0 }, 254 | { doingSomething14, 75000L, 0, 0 }, 255 | { doingSomething15, 80000L, 0, 0 } 256 | }; 257 | 258 | void doingSomething(int index) 259 | { 260 | unsigned long currentMillis = millis(); 261 | 262 | curISRTimerData[index].deltaMillis = currentMillis - curISRTimerData[index].previousMillis; 263 | curISRTimerData[index].previousMillis = currentMillis; 264 | } 265 | 266 | #else 267 | 268 | irqCallback irqCallbackFunc[NUMBER_ISR_TIMERS] = 269 | { 270 | doingSomething0, doingSomething1, doingSomething2, doingSomething3, 271 | doingSomething4, doingSomething5, doingSomething6, doingSomething7, 272 | doingSomething8, doingSomething9, doingSomething10, doingSomething11, 273 | doingSomething12, doingSomething13, doingSomething14, doingSomething15 274 | }; 275 | 276 | #endif 277 | /////////////////////////////////////////// 278 | 279 | #define SIMPLE_TIMER_MS 2000L 280 | 281 | // Init SimpleTimer 282 | SimpleTimer simpleTimer; 283 | 284 | // Here is software Timer, you can do somewhat fancy stuffs without many issues. 285 | // But always avoid 286 | // 1. Long delay() it just doing nothing and pain-without-gain wasting CPU power.Plan and design your code / strategy ahead 287 | // 2. Very long "do", "while", "for" loops without predetermined exit time. 288 | void simpleTimerDoingSomething2s() 289 | { 290 | static unsigned long previousMillis = startMillis; 291 | 292 | unsigned long currMillis = millis(); 293 | 294 | Serial.print(F("SimpleTimer : ")); Serial.print(SIMPLE_TIMER_MS / 1000); 295 | Serial.print(F(", ms : ")); Serial.print(currMillis); 296 | Serial.print(F(", Dms : ")); Serial.println(currMillis - previousMillis); 297 | 298 | for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++) 299 | { 300 | #if USE_COMPLEX_STRUCT 301 | Serial.print(F("Timer : ")); Serial.print(i); 302 | Serial.print(F(", programmed : ")); Serial.print(curISRTimerData[i].TimerInterval); 303 | Serial.print(F(", actual : ")); Serial.println(curISRTimerData[i].deltaMillis); 304 | #else 305 | Serial.print(F("Timer : ")); Serial.print(i); 306 | Serial.print(F(", programmed : ")); Serial.print(TimerInterval[i]); 307 | Serial.print(F(", actual : ")); Serial.println(deltaMillis[i]); 308 | #endif 309 | } 310 | 311 | previousMillis = currMillis; 312 | } 313 | 314 | void setup() 315 | { 316 | pinMode(LED_BUILTIN, OUTPUT); 317 | 318 | Serial.begin(115200); 319 | while (!Serial); 320 | 321 | delay(100); 322 | 323 | Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on ")); Serial.println(BOARD_NAME); 324 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 325 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 326 | 327 | // Interval in microsecs 328 | if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler)) 329 | { 330 | startMillis = millis(); 331 | Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(startMillis); 332 | } 333 | else 334 | Serial.println(F("Can't set ITimer. Select another freq. or timer")); 335 | 336 | startMillis = millis(); 337 | 338 | // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary 339 | // You can use up to 16 timer for each ISR_Timer 340 | for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++) 341 | { 342 | #if USE_COMPLEX_STRUCT 343 | curISRTimerData[i].previousMillis = startMillis; 344 | ISR_Timer.setInterval(curISRTimerData[i].TimerInterval, curISRTimerData[i].irqCallbackFunc); 345 | #else 346 | previousMillis[i] = millis(); 347 | ISR_Timer.setInterval(TimerInterval[i], irqCallbackFunc[i]); 348 | #endif 349 | } 350 | 351 | // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary. 352 | simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s); 353 | } 354 | 355 | #define BLOCKING_TIME_MS 10000L 356 | 357 | void loop() 358 | { 359 | // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer 360 | // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer 361 | // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS) 362 | // While that of ISR_Timer is still prefect. 363 | delay(BLOCKING_TIME_MS); 364 | 365 | // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary 366 | // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer. 367 | simpleTimer.run(); 368 | } 369 | -------------------------------------------------------------------------------- /examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | ISR_Timers_Array_Simple.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | 23 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 24 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 25 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 26 | #define TIMER_INTERRUPT_DEBUG 1 27 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 28 | 29 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 30 | #include "RPi_Pico_TimerInterrupt.h" 31 | 32 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 33 | #include "RPi_Pico_ISR_Timer.h" 34 | 35 | #include // https://github.com/jfturcot/SimpleTimer 36 | 37 | // Init RPI_PICO_Timer 38 | RPI_PICO_Timer ITimer1(1); 39 | 40 | RPI_PICO_ISR_Timer ISR_timer; 41 | 42 | #ifndef LED_BUILTIN 43 | #define LED_BUILTIN 25 44 | #endif 45 | 46 | #define LED_TOGGLE_INTERVAL_MS 1000L 47 | 48 | // You have to use longer time here if having problem because Arduino AVR clock is low, 16MHz => lower accuracy. 49 | // Tested OK with 1ms when not much load => higher accuracy. 50 | #define TIMER_INTERVAL_MS 1L 51 | 52 | volatile uint32_t startMillis = 0; 53 | 54 | volatile uint32_t deltaMillis2s = 0; 55 | volatile uint32_t deltaMillis5s = 0; 56 | 57 | volatile uint32_t previousMillis2s = 0; 58 | volatile uint32_t previousMillis5s = 0; 59 | 60 | 61 | bool TimerHandler(struct repeating_timer *t) 62 | { 63 | (void) t; 64 | 65 | static bool toggle = false; 66 | static int timeRun = 0; 67 | 68 | ISR_timer.run(); 69 | 70 | // Toggle LED every LED_TOGGLE_INTERVAL_MS = 2000ms = 2s 71 | if (++timeRun == ((LED_TOGGLE_INTERVAL_MS) / TIMER_INTERVAL_MS) ) 72 | { 73 | timeRun = 0; 74 | 75 | //timer interrupt toggles pin LED_BUILTIN 76 | digitalWrite(LED_BUILTIN, toggle); 77 | toggle = !toggle; 78 | } 79 | 80 | return true; 81 | } 82 | 83 | void doingSomething2s() 84 | { 85 | unsigned long currentMillis = millis(); 86 | 87 | deltaMillis2s = currentMillis - previousMillis2s; 88 | previousMillis2s = currentMillis; 89 | } 90 | 91 | void doingSomething5s() 92 | { 93 | unsigned long currentMillis = millis(); 94 | 95 | deltaMillis5s = currentMillis - previousMillis5s; 96 | previousMillis5s = currentMillis; 97 | } 98 | 99 | ///////////////////////////////////////////////// 100 | 101 | #define SIMPLE_TIMER_MS 2000L 102 | 103 | // Init SimpleTimer 104 | SimpleTimer simpleTimer; 105 | 106 | // Here is software Timer, you can do somewhat fancy stuffs without many issues. 107 | // But always avoid 108 | // 1. Long delay() it just doing nothing and pain-without-gain wasting CPU power.Plan and design your code / strategy ahead 109 | // 2. Very long "do", "while", "for" loops without predetermined exit time. 110 | void simpleTimerDoingSomething2s() 111 | { 112 | static unsigned long previousMillis = startMillis; 113 | 114 | unsigned long currMillis = millis(); 115 | 116 | Serial.print(F("SimpleTimer : programmed ")); Serial.print(SIMPLE_TIMER_MS); 117 | Serial.print(F("ms, current time ms : ")); Serial.print(currMillis); 118 | Serial.print(F(", Delta ms : ")); Serial.println(currMillis - previousMillis); 119 | 120 | Serial.print(F("Timer2s actual : ")); Serial.println(deltaMillis2s); 121 | Serial.print(F("Timer5s actual : ")); Serial.println(deltaMillis5s); 122 | 123 | previousMillis = currMillis; 124 | } 125 | 126 | //////////////////////////////////////////////// 127 | 128 | void setup() 129 | { 130 | pinMode(LED_BUILTIN, OUTPUT); 131 | 132 | Serial.begin(115200); 133 | while (!Serial); 134 | 135 | Serial.print(F("\nStarting ISR_Timers_Array_Simple on ")); Serial.println(BOARD_NAME); 136 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 137 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 138 | 139 | if (ITimer1.attachInterruptInterval(TIMER_INTERVAL_MS * 1000, TimerHandler)) 140 | { 141 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 142 | } 143 | else 144 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 145 | 146 | previousMillis5s = previousMillis2s = millis(); 147 | 148 | ISR_timer.setInterval(2000L, doingSomething2s); 149 | ISR_timer.setInterval(5000L, doingSomething5s); 150 | 151 | // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary. 152 | simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s); 153 | } 154 | 155 | #define BLOCKING_TIME_MS 10000L 156 | 157 | void loop() 158 | { 159 | // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer 160 | // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer 161 | // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS) 162 | // While that of ISR_Timer is still prefect. 163 | delay(BLOCKING_TIME_MS); 164 | 165 | // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary 166 | // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer. 167 | simpleTimer.run(); 168 | } 169 | -------------------------------------------------------------------------------- /examples/RPM_Measure/RPM_Measure.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | RPM_Measure.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | /* 23 | Notes: 24 | Special design is necessary to share data between interrupt code and the rest of your program. 25 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 26 | variable can not spontaneously change. Because your function may change variables while your program is using them, 27 | the compiler needs this hint. But volatile alone is often not enough. 28 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 29 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 30 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 31 | or the entire sequence of your code which accesses the data. 32 | 33 | RPM Measuring uses high frequency hardware timer 1Hz == 1ms) to measure the time from of one rotation, in ms 34 | then convert to RPM. One rotation is detected by reading the state of a magnetic REED SW or IR LED Sensor 35 | Asssuming LOW is active. 36 | For example: Max speed is 600RPM => 10 RPS => minimum 100ms a rotation. We'll use 80ms for debouncing 37 | If the time between active state is less than 8ms => consider noise. 38 | RPM = 60000 / (rotation time in ms) 39 | 40 | You can also use interrupt to detect whenever the SW is active, set a flag then use timer to count the time between active state 41 | */ 42 | 43 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 44 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 45 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 46 | #define TIMER_INTERRUPT_DEBUG 1 47 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 48 | 49 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 50 | #include "RPi_Pico_TimerInterrupt.h" 51 | 52 | #define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of RPI_PICO 53 | 54 | unsigned int SWPin = PIN_D1; 55 | 56 | #define TIMER0_INTERVAL_MS 1 57 | #define DEBOUNCING_INTERVAL_MS 80 58 | 59 | #define LOCAL_DEBUG 1 60 | 61 | // Init RPI_PICO_Timer, can use any from 0-15 pseudo-hardware timers 62 | RPI_PICO_Timer ITimer0(0); 63 | 64 | volatile unsigned long rotationTime = 0; 65 | float RPM = 0.00; 66 | float avgRPM = 0.00; 67 | 68 | volatile int debounceCounter; 69 | 70 | bool TimerHandler0(struct repeating_timer *t) 71 | { 72 | (void) t; 73 | 74 | if ( !digitalRead(SWPin) && (debounceCounter >= DEBOUNCING_INTERVAL_MS / TIMER0_INTERVAL_MS ) ) 75 | { 76 | //min time between pulses has passed 77 | RPM = (float) ( 60000.0f / ( rotationTime * TIMER0_INTERVAL_MS ) ); 78 | 79 | avgRPM = ( 2 * avgRPM + RPM) / 3, 80 | 81 | #if (TIMER_INTERRUPT_DEBUG > 0) 82 | Serial.print("RPM = "); Serial.print(avgRPM); 83 | Serial.print(", rotationTime ms = "); Serial.println(rotationTime * TIMER0_INTERVAL_MS); 84 | #endif 85 | 86 | rotationTime = 0; 87 | debounceCounter = 0; 88 | } 89 | else 90 | { 91 | debounceCounter++; 92 | } 93 | 94 | if (rotationTime >= 5000) 95 | { 96 | // If idle, set RPM to 0, don't increase rotationTime 97 | RPM = 0; 98 | 99 | #if (TIMER_INTERRUPT_DEBUG > 0) 100 | Serial.print("RPM = "); Serial.print(RPM); Serial.print(", rotationTime = "); Serial.println(rotationTime); 101 | #endif 102 | 103 | rotationTime = 0; 104 | } 105 | else 106 | { 107 | rotationTime++; 108 | } 109 | 110 | return true; 111 | } 112 | 113 | void setup() 114 | { 115 | pinMode(SWPin, INPUT_PULLUP); 116 | 117 | Serial.begin(115200); 118 | while (!Serial); 119 | 120 | delay(100); 121 | 122 | Serial.print(F("\nStarting RPM_Measure on ")); Serial.println(BOARD_NAME); 123 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 124 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 125 | 126 | // Using ESP32 => 80 / 160 / 240MHz CPU clock , 127 | // For 64-bit timer counter 128 | // For 16-bit timer prescaler up to 1024 129 | 130 | // Interval in microsecs 131 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 132 | { 133 | Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis()); 134 | } 135 | else 136 | Serial.println(F("Can't set ITimer0. Select another freq. or timer")); 137 | 138 | Serial.flush(); 139 | } 140 | 141 | void loop() 142 | { 143 | 144 | } 145 | -------------------------------------------------------------------------------- /examples/SwitchDebounce/SwitchDebounce.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | SwitchDebounce.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | /* 23 | Notes: 24 | Special design is necessary to share data between interrupt code and the rest of your program. 25 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 26 | variable can not spontaneously change. Because your function may change variables while your program is using them, 27 | the compiler needs this hint. But volatile alone is often not enough. 28 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 29 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 30 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 31 | or the entire sequence of your code which accesses the data. 32 | 33 | Switch Debouncing uses high frequency hardware timer 50Hz == 20ms) to measure the time from the SW is pressed, 34 | debouncing time is 100ms => SW is considered pressed if timer count is > 5, then call / flag SW is pressed 35 | When the SW is released, timer will count (debounce) until more than 50ms until consider SW is released. 36 | We can set to flag or call a function whenever SW is pressed more than certain predetermined time, even before 37 | SW is released. 38 | */ 39 | 40 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 41 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 42 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 43 | #define TIMER_INTERRUPT_DEBUG 1 44 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 45 | 46 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 47 | #include "RPi_Pico_TimerInterrupt.h" 48 | 49 | #define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of RPI_PICO 50 | 51 | unsigned int SWPin = PIN_D1; 52 | 53 | #define TIMER1_INTERVAL_MS 20 54 | #define DEBOUNCING_INTERVAL_MS 100 55 | #define LONG_PRESS_INTERVAL_MS 5000 56 | 57 | #define LOCAL_DEBUG 2 58 | 59 | // Init RPI_PICO_Timer, can use any from 0-15 pseudo-hardware timers 60 | RPI_PICO_Timer ITimer1(1); 61 | 62 | volatile bool SWPressed = false; 63 | volatile bool SWLongPressed = false; 64 | 65 | bool TimerHandler1(struct repeating_timer *t) 66 | { 67 | (void) t; 68 | 69 | static unsigned int debounceCountSWPressed = 0; 70 | static unsigned int debounceCountSWReleased = 0; 71 | 72 | #if (LOCAL_DEBUG > 1) 73 | static unsigned long SWPressedTime; 74 | static unsigned long SWReleasedTime; 75 | 76 | unsigned long currentMillis = millis(); 77 | #endif 78 | 79 | if ( (!digitalRead(SWPin)) ) 80 | { 81 | // Start debouncing counting debounceCountSWPressed and clear debounceCountSWReleased 82 | debounceCountSWReleased = 0; 83 | 84 | if (++debounceCountSWPressed >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS) 85 | { 86 | // Call and flag SWPressed 87 | if (!SWPressed) 88 | { 89 | #if (LOCAL_DEBUG > 1) 90 | SWPressedTime = currentMillis; 91 | 92 | Serial.print("SW Press, from millis() = "); Serial.println(SWPressedTime); 93 | #endif 94 | 95 | SWPressed = true; 96 | // Do something for SWPressed here in ISR 97 | // But it's better to use outside software timer to do your job instead of inside ISR 98 | //Your_Response_To_Press(); 99 | } 100 | 101 | if (debounceCountSWPressed >= LONG_PRESS_INTERVAL_MS / TIMER1_INTERVAL_MS) 102 | { 103 | // Call and flag SWLongPressed 104 | if (!SWLongPressed) 105 | { 106 | #if (LOCAL_DEBUG > 1) 107 | Serial.print("SW Long Pressed, total time ms = "); Serial.print(currentMillis); 108 | Serial.print(" - "); Serial.print(SWPressedTime); 109 | Serial.print(" = "); Serial.println(currentMillis - SWPressedTime); 110 | #endif 111 | 112 | SWLongPressed = true; 113 | // Do something for SWLongPressed here in ISR 114 | // But it's better to use outside software timer to do your job instead of inside ISR 115 | //Your_Response_To_Long_Press(); 116 | } 117 | } 118 | } 119 | } 120 | else 121 | { 122 | // Start debouncing counting debounceCountSWReleased and clear debounceCountSWPressed 123 | if ( SWPressed && (++debounceCountSWReleased >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS)) 124 | { 125 | #if (LOCAL_DEBUG > 1) 126 | SWReleasedTime = currentMillis; 127 | 128 | // Call and flag SWPressed 129 | Serial.print("SW Released, from millis() = "); Serial.println(SWReleasedTime); 130 | #endif 131 | 132 | SWPressed = false; 133 | SWLongPressed = false; 134 | 135 | // Do something for !SWPressed here in ISR 136 | // But it's better to use outside software timer to do your job instead of inside ISR 137 | //Your_Response_To_Release(); 138 | 139 | // Call and flag SWPressed 140 | #if (LOCAL_DEBUG > 1) 141 | Serial.print("SW Pressed total time ms = "); 142 | Serial.println(SWReleasedTime - SWPressedTime); 143 | #endif 144 | 145 | debounceCountSWPressed = 0; 146 | } 147 | } 148 | 149 | return true; 150 | } 151 | 152 | void setup() 153 | { 154 | pinMode(SWPin, INPUT_PULLUP); 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(RPI_PICO_TIMER_INTERRUPT_VERSION); 163 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 164 | 165 | // Interval in microsecs 166 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 167 | { 168 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 169 | } 170 | else 171 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 172 | } 173 | 174 | void loop() 175 | { 176 | 177 | } 178 | -------------------------------------------------------------------------------- /examples/TimerInterruptTest/TimerInterruptTest.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | TimerInterruptTest.ino 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | *****************************************************************************************************************************/ 22 | /* 23 | Notes: 24 | Special design is necessary to share data between interrupt code and the rest of your program. 25 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume 26 | variable can not spontaneously change. Because your function may change variables while your program is using them, 27 | the compiler needs this hint. But volatile alone is often not enough. 28 | When accessing shared variables, usually interrupts must be disabled. Even with volatile, 29 | if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. 30 | If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled 31 | or the entire sequence of your code which accesses the data. 32 | */ 33 | 34 | // These define's must be placed at the beginning before #include "TimerInterrupt_Generic.h" 35 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 36 | // Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. 37 | #define TIMER_INTERRUPT_DEBUG 1 38 | #define _TIMERINTERRUPT_LOGLEVEL_ 4 39 | 40 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 41 | #include "RPi_Pico_TimerInterrupt.h" 42 | 43 | #ifndef LED_BUILTIN 44 | #define LED_BUILTIN 25 45 | #endif 46 | 47 | #define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of RPI_PICO 48 | 49 | bool TimerHandler0(struct repeating_timer *t) 50 | { 51 | (void) t; 52 | 53 | static bool toggle0 = false; 54 | static bool started = false; 55 | 56 | if (!started) 57 | { 58 | started = true; 59 | pinMode(LED_BUILTIN, OUTPUT); 60 | } 61 | 62 | #if (TIMER_INTERRUPT_DEBUG > 0) 63 | Serial.print("ITimer0 called, millis() = "); Serial.println(millis()); 64 | #endif 65 | 66 | //timer interrupt toggles pin LED_BUILTIN 67 | digitalWrite(LED_BUILTIN, toggle0); 68 | toggle0 = !toggle0; 69 | 70 | return true; 71 | } 72 | 73 | bool TimerHandler1(struct repeating_timer *t) 74 | { 75 | (void) t; 76 | 77 | static bool toggle1 = false; 78 | static bool started = false; 79 | 80 | if (!started) 81 | { 82 | started = true; 83 | pinMode(PIN_D1, OUTPUT); 84 | } 85 | 86 | #if (TIMER_INTERRUPT_DEBUG > 0) 87 | Serial.print("ITimer1 called, millis() = "); Serial.println(millis()); 88 | #endif 89 | 90 | //timer interrupt toggles outputPin 91 | digitalWrite(PIN_D1, toggle1); 92 | toggle1 = !toggle1; 93 | 94 | return true; 95 | } 96 | 97 | #define TIMER0_INTERVAL_MS 1000 98 | #define TIMER0_DURATION_MS 5000 99 | 100 | #define TIMER1_INTERVAL_MS 3000 101 | #define TIMER1_DURATION_MS 15000 102 | 103 | // Init RPI_PICO_Timer, can use any from 0-15 pseudo-hardware timers 104 | RPI_PICO_Timer ITimer0(0); 105 | RPI_PICO_Timer ITimer1(1); 106 | 107 | void setup() 108 | { 109 | Serial.begin(115200); 110 | while (!Serial); 111 | 112 | delay(100); 113 | 114 | Serial.print(F("\nStarting TimerInterruptTest on ")); Serial.println(BOARD_NAME); 115 | Serial.println(RPI_PICO_TIMER_INTERRUPT_VERSION); 116 | Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); 117 | 118 | // Interval in microsecs 119 | if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) 120 | { 121 | Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis()); 122 | } 123 | else 124 | Serial.println(F("Can't set ITimer0. Select another freq. or timer")); 125 | 126 | // Interval in microsecs 127 | if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) 128 | { 129 | Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); 130 | } 131 | else 132 | Serial.println(F("Can't set ITimer1. Select another freq. or timer")); 133 | 134 | Serial.flush(); 135 | } 136 | 137 | void loop() 138 | { 139 | static unsigned long lastTimer0 = 0; 140 | static unsigned long lastTimer1 = 0; 141 | 142 | static bool timer0Stopped = false; 143 | static bool timer1Stopped = false; 144 | 145 | if (millis() - lastTimer0 > TIMER0_DURATION_MS) 146 | { 147 | lastTimer0 = millis(); 148 | 149 | if (timer0Stopped) 150 | { 151 | Serial.print(F("Start ITimer0, millis() = ")); Serial.println(millis()); 152 | ITimer0.restartTimer(); 153 | } 154 | else 155 | { 156 | Serial.print(F("Stop ITimer0, millis() = ")); Serial.println(millis()); 157 | ITimer0.stopTimer(); 158 | } 159 | timer0Stopped = !timer0Stopped; 160 | } 161 | 162 | if (millis() - lastTimer1 > TIMER1_DURATION_MS) 163 | { 164 | lastTimer1 = millis(); 165 | 166 | if (timer1Stopped) 167 | { 168 | Serial.print(F("Start ITimer1, millis() = ")); Serial.println(millis()); 169 | ITimer1.restartTimer(); 170 | } 171 | else 172 | { 173 | Serial.print(F("Stop ITimer1, millis() = ")); Serial.println(millis()); 174 | ITimer1.stopTimer(); 175 | } 176 | 177 | timer1Stopped = !timer1Stopped; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.cpp 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_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 SAMD 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 | 17 | // To demo how to include files in multi-file Projects 18 | 19 | #include "multiFileProject.h" 20 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.h 3 | RPi_Pico_ISR_Timer-Impl.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_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 SAMD 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 | 17 | // To demo how to include files in multi-file Projects 18 | 19 | #pragma once 20 | 21 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 22 | #include "RPi_Pico_TimerInterrupt.h" 23 | 24 | // Can be included as many times as necessary, without `Multiple Definitions` Linker Error 25 | #include "RPi_Pico_ISR_Timer.hpp" 26 | -------------------------------------------------------------------------------- /examples/multiFileProject/multiFileProject.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | multiFileProject.ino 3 | For Teensy boards 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/Teensy_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_ARCH_RP2040) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_GENERIC_RP2040) ) && !defined(ARDUINO_ARCH_MBED) 19 | #error This code is intended to run on the non-mbed RP2040 arduino-pico 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 "RPi_Pico_TimerInterrupt.h" 26 | 27 | // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error 28 | #include "RPi_Pico_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 | RPI_PICO_TimerInterrupt KEYWORD1 6 | RPI_PICO_Timer KEYWORD1 7 | RPI_PICO_ISR_Timer KEYWORD1 8 | 9 | ####################################### 10 | # Methods and Functions (KEYWORD2) 11 | ####################################### 12 | 13 | ########################### 14 | # RPi_Pico_TimerInterrupt 15 | ########################### 16 | 17 | setFrequency KEYWORD2 18 | setInterval KEYWORD2 19 | attachInterrupt KEYWORD2 20 | attachInterruptInterval KEYWORD2 21 | detachInterrupt KEYWORD2 22 | disableTimer KEYWORD2 23 | reattachInterrupt KEYWORD2 24 | enableTimer KEYWORD2 25 | stopTimer KEYWORD2 26 | restartTimer KEYWORD2 27 | 28 | ########################### 29 | # RPi_Pico_ISR_Timer 30 | ########################### 31 | 32 | init KEYWORD2 33 | run KEYWORD2 34 | setTimeout KEYWORD2 35 | setTimer KEYWORD2 36 | changeInterval KEYWORD2 37 | deleteTimer KEYWORD2 38 | restartTimer KEYWORD2 39 | isEnabled KEYWORD2 40 | enable KEYWORD2 41 | disable KEYWORD2 42 | enableAll KEYWORD2 43 | disableAll KEYWORD2 44 | toggle KEYWORD2 45 | getNumTimers KEYWORD2 46 | getNumAvailableTimers KEYWORD2 47 | 48 | ####################################### 49 | # Constants (LITERAL1) 50 | ####################################### 51 | 52 | RPI_PICO_TIMER_INTERRUPT_VERSION LITERAL1 53 | RPI_PICO_TIMER_INTERRUPT_VERSION_MAJOR LITERAL1 54 | RPI_PICO_TIMER_INTERRUPT_VERSION_MINOR LITERAL1 55 | RPI_PICO_TIMER_INTERRUPT_VERSION_PATCH LITERAL1 56 | RPI_PICO_TIMER_INTERRUPT_VERSION_INT LITERAL1 57 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RPI_PICO_TimerInterrupt", 3 | "version": "1.3.1", 4 | "keywords": "timing, device, control, timer, interrupt, hardware, isr, isr-based, hardware-timer, mission-critical, accuracy, non-blocking, raspberry-pico, rpi-pico, pico, rp2040, arduino-pico, rp2040w, raspberry-pico-w, pico-w", 5 | "description": "This library enables you to use Interrupt from Hardware Timers on RP2040-based boards such as RASPBERRY_PI_PICO. 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.", 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/RPI_PICO_TimerInterrupt" 16 | }, 17 | "homepage": "https://github.com/khoih-prog/RPI_PICO_TimerInterrupt", 18 | "export": { 19 | "exclude": [ 20 | "linux", 21 | "extras", 22 | "tests" 23 | ] 24 | }, 25 | "license": "MIT", 26 | "frameworks": "*", 27 | "platforms": ["raspberrypi"], 28 | "examples": "examples/*/*/*.ino", 29 | "headers": ["RPi_Pico_TimerInterrupt.h", "RPi_Pico_ISR_Timer.h", "RPi_Pico_ISR_Timer.hpp"] 30 | } 31 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=RPI_PICO_TimerInterrupt 2 | version=1.3.1 3 | author=Khoi Hoang 4 | maintainer=Khoi Hoang 5 | sentence=This library enables you to use Interrupt from Hardware Timers on RP2040-based boards such as RASPBERRY_PI_PICO 6 | paragraph=These RPI_PICO_TimerInterrupt 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 is 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 are 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/RPI_PICO_TimerInterrupt 9 | architectures=rp2040 10 | repository=https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 11 | license=MIT 12 | includes=RPi_Pico_TimerInterrupt.h,RPi_Pico_ISR_Timer.h,RPi_Pico_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 = mbed_pico 26 | ;default_envs = NRF52 27 | ;default_envs = STM32 28 | ;default_envs = portenta_h7_m7 29 | ;default_envs = portenta_h7_m4 30 | 31 | [env] 32 | ; ============================================================ 33 | ; Serial configuration 34 | ; choose upload speed, serial-monitor speed 35 | ; ============================================================ 36 | upload_speed = 921600 37 | ;upload_port = COM11 38 | ;monitor_speed = 9600 39 | ;monitor_port = COM11 40 | 41 | ; Checks for the compatibility with frameworks and dev/platforms 42 | lib_compat_mode = strict 43 | lib_ldf_mode = chain+ 44 | ;lib_ldf_mode = deep+ 45 | 46 | lib_deps = 47 | 48 | 49 | build_flags = 50 | ; set your debug output (default=Serial) 51 | ; -D DEBUG_ESP_PORT=Serial 52 | ; comment the following line to enable WiFi debugging 53 | ; -D NDEBUG 54 | 55 | [env:portenta_h7_m7] 56 | platform = ststm32 57 | board = portenta_h7_m7 58 | framework = arduino 59 | 60 | [env:portenta_h7_m4] 61 | platform = ststm32 62 | board = portenta_h7_m4 63 | framework = arduino 64 | 65 | [env:pico] 66 | ; ============================================================ 67 | ; Just a sample for arduino-pice core 68 | ; You have to research and fix if there is issue 69 | ; ============================================================ 70 | platform = https://github.com/maxgerhardt/platform-raspberrypi.git 71 | board = pico 72 | framework = arduino 73 | board_build.core = earlephilhower 74 | 75 | [env:mbed_pico] 76 | ; ============================================================ 77 | ; Just a sample for mbed_rp2040 and mbed_nano cores 78 | ; You have to research and fix if there is issue 79 | ; ============================================================ 80 | platform = raspberrypi 81 | board = pico 82 | framework = arduino 83 | upload_protocol = picotool 84 | 85 | [env:ESP8266] 86 | platform = espressif8266 87 | framework = arduino 88 | ; ============================================================ 89 | ; Board configuration 90 | ; choose your board by uncommenting one of the following lines 91 | ; ============================================================ 92 | ;board = gen4iod 93 | ;board = huzzah 94 | ;board = oak 95 | ;board = esp_wroom_02 96 | ;board = espduino 97 | ;board = espectro 98 | ;board = espino 99 | ;board = espresso_lite_v1 100 | ;board = espresso_lite_v2 101 | ;board = esp12e 102 | ;board = esp01_1m 103 | ;board = esp01 104 | ;board = esp07 105 | ;board = esp8285 106 | ;board = heltec_wifi_kit_8 107 | ;board = inventone 108 | ;board = nodemcu 109 | board = nodemcuv2 110 | ;board = modwifi 111 | ;board = phoenix_v1 112 | ;board = phoenix_v2 113 | ;board = sparkfunBlynk 114 | ;board = thing 115 | ;board = thingdev 116 | ;board = esp210 117 | ;board = espinotee 118 | ;board = d1 119 | ;board = d1_mini 120 | ;board = d1_mini_lite 121 | ;board = d1_mini_pro 122 | ;board = wifi_slot 123 | ;board = wifiduino 124 | ;board = wifinfo 125 | ;board = wio_link 126 | ;board = wio_node 127 | ;board = xinabox_cw01 128 | ;board = esp32doit-devkit-v1 129 | 130 | [env:ESP32] 131 | platform = espressif32 132 | framework = arduino 133 | ; ============================================================ 134 | ; Board configuration 135 | ; choose your board by uncommenting one of the following lines 136 | ; ============================================================ 137 | ;board = esp32cam 138 | ;board = alksesp32 139 | ;board = featheresp32 140 | ;board = espea32 141 | ;board = bpi-bit 142 | ;board = d-duino-32 143 | board = esp32doit-devkit-v1 144 | ;board = pocket_32 145 | ;board = fm-devkit 146 | ;board = pico32 147 | ;board = esp32-evb 148 | ;board = esp32-gateway 149 | ;board = esp32-pro 150 | ;board = esp32-poe 151 | ;board = oroca_edubot 152 | ;board = onehorse32dev 153 | ;board = lopy 154 | ;board = lopy4 155 | ;board = wesp32 156 | ;board = esp32thing 157 | ;board = sparkfun_lora_gateway_1-channel 158 | ;board = ttgo-lora32-v1 159 | ;board = ttgo-t-beam 160 | ;board = turta_iot_node 161 | ;board = lolin_d32 162 | ;board = lolin_d32_pro 163 | ;board = lolin32 164 | ;board = wemosbat 165 | ;board = widora-air 166 | ;board = xinabox_cw02 167 | ;board = iotbusio 168 | ;board = iotbusproteus 169 | ;board = nina_w10 170 | 171 | [env:SAMD] 172 | platform = atmelsam 173 | framework = arduino 174 | ; ============================================================ 175 | ; Choose your board by uncommenting one of the following lines 176 | ; ============================================================ 177 | ; ============================================================ 178 | ; Board configuration Adafruit SAMD 179 | ; ============================================================ 180 | 181 | ;board = adafruit_feather_m0 182 | ;board = adafruit_feather_m0_express 183 | ;board = adafruit_metro_m0 184 | ;board = adafruit_circuitplayground_m0 185 | ;board = adafruit_gemma_m0 186 | ;board = adafruit_trinket_m0 187 | ;board = adafruit_itsybitsy_m0 188 | ;board = adafruit_pirkey 189 | ;board = adafruit_hallowing 190 | ;board = adafruit_crickit_m0 191 | ;board = adafruit_metro_m4 192 | ;board = adafruit_grandcentral_m4 193 | board = adafruit_itsybitsy_m4 194 | ;board = adafruit_feather_m4 195 | ;board = adafruit_trellis_m4 196 | ;board = adafruit_pyportal_m4 197 | ;board = adafruit_pyportal_m4_titano 198 | ;board = adafruit_pybadge_m4 199 | ;board = adafruit_metro_m4_airliftlite 200 | ;board = adafruit_pygamer_m4 201 | ;board = adafruit_pygamer_advance_m4 202 | ;board = adafruit_pybadge_airlift_m4 203 | ;board = adafruit_monster_m4sk 204 | ;board = adafruit_hallowing_m4 205 | 206 | ; ============================================================ 207 | ; Board configuration Arduino SAMD and SAM 208 | ; ============================================================ 209 | 210 | ;board = arduino_zero_edbg 211 | ;board = arduino_zero_native 212 | ;board = mkr1000 213 | ;board = mkrzero 214 | ;board = mkrwifi1010 215 | ;board = nano_33_iot 216 | ;board = mkrfox1200 217 | ;board = mkrwan1300 218 | ;board = mkrwan1310 219 | ;board = mkrgsm1400 220 | ;board = mkrnb1500 221 | ;board = mkrvidor4000 222 | ;board = adafruit_circuitplayground_m0 223 | ;board = mzero_pro_bl_dbg 224 | ;board = mzero_pro_bl 225 | ;board = mzero_bl 226 | ;board = tian 227 | ;board = tian_cons 228 | ;board = arduino_due_x_dbg 229 | ;board = arduino_due_x 230 | 231 | ; ============================================================ 232 | ; Board configuration Seeeduino SAMD 233 | ; ============================================================ 234 | 235 | ;board = seeed_wio_terminal 236 | ;board = Seeed_femto_m0 237 | ;board = seeed_XIAO_m0 238 | ;board = Wio_Lite_MG126 239 | ;board = WioGPS 240 | ;board = zero 241 | ;board = rolawan 242 | ;board = seeed_grove_ui_wireless 243 | 244 | 245 | [env:NRF52] 246 | platform = nordicnrf52 247 | framework = arduino 248 | ; ============================================================ 249 | ; Board configuration Adafruit nRF52 250 | ; choose your board by uncommenting one of the following lines 251 | ; ============================================================ 252 | ;board = feather52832 253 | board = feather52840 254 | ;board = feather52840sense 255 | ;board = itsybitsy52840 256 | ;board = cplaynrf52840 257 | ;board = cluenrf52840 258 | ;board = metro52840 259 | ;board = pca10056 260 | ;board = particle_xenon 261 | ;board = mdbt50qrx 262 | ;board = ninab302 263 | ;board = ninab112 264 | 265 | [env:STM32] 266 | platform = ststm32 267 | framework = arduino 268 | 269 | ; ============================================================ 270 | ; Choose your board by uncommenting one of the following lines 271 | ; ============================================================ 272 | 273 | ; ============================================================ 274 | ; Board configuration Nucleo-144 275 | ; ============================================================ 276 | 277 | ;board = nucleo_f207zg 278 | ;board = nucleo_f429zi 279 | ;board = nucleo_f746zg 280 | ;board = nucleo_f756zg 281 | ;board = nucleo_f767zi 282 | ;board = nucleo_h743zi 283 | ;board = nucleo_l496zg 284 | ;board = nucleo_l496zg-p 285 | ;board = nucleo_l4r5zi 286 | ;board = nucleo_l4r5zi-p 287 | 288 | ; ============================================================ 289 | ; Board configuration Nucleo-64 290 | ; ============================================================ 291 | 292 | ;board = nucleo_f030r8 293 | ;board = nucleo_f072rb 294 | 295 | ;board = nucleo_f091rc 296 | ;board = nucleo_f103rb 297 | ;board = nucleo_f302r8 298 | ;board = nucleo_f303re 299 | ;board = nucleo_f401re 300 | ;board = nucleo_f411re 301 | ;board = nucleo_f446re 302 | ;board = nucleo_g071rb 303 | ;board = nucleo_g431rb 304 | ;board = nucleo_g474re 305 | ;board = nucleo_l053r8 306 | ;board = nucleo_l073rz 307 | ;board = nucleo_l152re 308 | ;board = nucleo_l433rc_p 309 | ;board = nucleo_l452re 310 | ;board = nucleo_l452re-p 311 | ;board = nucleo_l476rg 312 | ;board = pnucleo_wb55rg 313 | 314 | ; ============================================================ 315 | ; Board configuration Nucleo-32 316 | ; ============================================================ 317 | 318 | ;board = nucleo_f031k6 319 | ;board = nucleo_l031k6 320 | ;board = nucleo_l412kb 321 | ;board = nucleo_l432lc 322 | ;board = nucleo_f303k8 323 | ;board = nucleo_g431kb 324 | 325 | ; ============================================================ 326 | ; Board configuration Discovery Boards 327 | ; ============================================================ 328 | 329 | ;board = disco_f030r8 330 | ;board = disco_f072rb 331 | ;board = disco_f030r8 332 | ;board = disco_f100rb 333 | ;board = disco_f407vg 334 | ;board = disco_f413zh 335 | ;board = disco_f746ng 336 | ;board = disco_g0316 337 | ;board = disco_l475vg_iot 338 | ;board = disco_f072cz-lrwan1 339 | 340 | ; ============================================================ 341 | ; Board configuration STM32MP1 Boards 342 | ; ============================================================ 343 | 344 | ;board = stm32mp157a-dk1 345 | ;board = stm32mp157c-dk2 346 | 347 | ; ============================================================ 348 | ; Board configuration Generic Boards 349 | ; ============================================================ 350 | 351 | ;board = bluepill_f103c6 352 | ;board = bluepill_f103c8 353 | ;board = blackpill_f103c8 354 | ;board = stm32f103cx 355 | ;board = stm32f103rx 356 | ;board = stm32f103tx 357 | ;board = stm32f103vx 358 | ;board = stm32f103zx 359 | ;board = stm32f103zet6 360 | ;board = maplemini_f103cb 361 | ;board = blackpill_f303cc 362 | ;board = black_f407ve 363 | ;board = black_f407vg 364 | ;board = black_f407ze 365 | ;board = black_f407zg 366 | ;board = blue_f407ve_mini 367 | ;board = blackpill_f401cc 368 | ;board = blackpill_f411ce 369 | ;board = coreboard_f401rc 370 | ;board = feather_f405 371 | 372 | ; ============================================================ 373 | ; Board configuration Many more Boards to be filled 374 | ; ============================================================ 375 | 376 | -------------------------------------------------------------------------------- /src/RPi_Pico_ISR_Timer-Impl.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | RPi_Pico_ISR_Timer-Impl.h 3 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 10 | interrupts based on this timebase. It supports the following features: 11 | • A single 64-bit counter, incrementing once per microsecond 12 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 13 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 14 | 15 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 16 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 17 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 18 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 19 | This important feature is absolutely necessary for mission-critical tasks. 20 | 21 | Based on SimpleTimer - A timer library for Arduino. 22 | Author: mromani@ottotecnica.com 23 | Copyright (c) 2010 OTTOTECNICA Italy 24 | 25 | Based on BlynkTimer.h 26 | Author: Volodymyr Shymanskyy 27 | 28 | Version: 1.3.1 29 | 30 | Version Modified By Date Comments 31 | ------- ----------- ---------- ----------- 32 | 1.0.0 K Hoang 11/05/2021 Initial coding to support RP2040-based boards such as RASPBERRY_PI_PICO. etc. 33 | 1.0.1 K Hoang 18/05/2021 Update README and Packages' Patches to match core arduino-pico core v1.4.0 34 | 1.1.0 K Hoang 10/00/2021 Add support to new boards using the arduino-pico core 35 | 1.1.1 K Hoang 22/10/2021 Fix platform in library.json for PIO 36 | 1.2.0 K.Hoang 21/01/2022 Fix `multiple-definitions` linker error 37 | 1.3.0 K.Hoang 25/09/2022 Fix severe bug affecting time between the starts 38 | 1.3.1 K.Hoang 29/09/2022 Using float instead of ulong for interval 39 | *****************************************************************************************************************************/ 40 | 41 | #pragma once 42 | 43 | #ifndef ISR_TIMER_GENERIC_IMPL_H 44 | #define ISR_TIMER_GENERIC_IMPL_H 45 | 46 | #include 47 | 48 | //////////////////////////////////////////////////////////////// 49 | 50 | RPI_PICO_ISR_Timer::RPI_PICO_ISR_Timer() 51 | : numTimers (-1) 52 | { 53 | } 54 | 55 | //////////////////////////////////////////////////////////////// 56 | 57 | void RPI_PICO_ISR_Timer::init() 58 | { 59 | unsigned long current_millis = millis(); //elapsed(); 60 | 61 | for (uint8_t i = 0; i < RPI_PICO_MAX_TIMERS; i++) 62 | { 63 | memset((void*) &timer[i], 0, sizeof (timer_t)); 64 | timer[i].prev_millis = current_millis; 65 | } 66 | 67 | numTimers = 0; 68 | } 69 | 70 | //////////////////////////////////////////////////////////////// 71 | 72 | void RPI_PICO_ISR_Timer::run() 73 | { 74 | uint8_t i; 75 | unsigned long current_millis; 76 | 77 | // get current time 78 | current_millis = millis(); //elapsed(); 79 | 80 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during ISR 81 | rp2040.idleOtherCore(); 82 | 83 | for (i = 0; i < RPI_PICO_MAX_TIMERS; i++) 84 | { 85 | 86 | timer[i].toBeCalled = RPI_PICO_DEFCALL_DONTRUN; 87 | 88 | // no callback == no timer, i.e. jump over empty slots 89 | if (timer[i].callback != NULL) 90 | { 91 | 92 | // is it time to process this timer ? 93 | // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592 94 | 95 | if ((current_millis - timer[i].prev_millis) >= timer[i].delay) 96 | { 97 | unsigned long skipTimes = (current_millis - timer[i].prev_millis) / timer[i].delay; 98 | 99 | // update time 100 | timer[i].prev_millis += timer[i].delay * skipTimes; 101 | 102 | // check if the timer callback has to be executed 103 | if (timer[i].enabled) 104 | { 105 | 106 | // "run forever" timers must always be executed 107 | if (timer[i].maxNumRuns == RPI_PICO_RUN_FOREVER) 108 | { 109 | timer[i].toBeCalled = RPI_PICO_DEFCALL_RUNONLY; 110 | } 111 | // other timers get executed the specified number of times 112 | else if (timer[i].numRuns < timer[i].maxNumRuns) 113 | { 114 | timer[i].toBeCalled = RPI_PICO_DEFCALL_RUNONLY; 115 | timer[i].numRuns++; 116 | 117 | // after the last run, delete the timer 118 | if (timer[i].numRuns >= timer[i].maxNumRuns) 119 | { 120 | timer[i].toBeCalled = RPI_PICO_DEFCALL_RUNANDDEL; 121 | } 122 | } 123 | } 124 | } 125 | } 126 | } 127 | 128 | for (i = 0; i < RPI_PICO_MAX_TIMERS; i++) 129 | { 130 | if (timer[i].toBeCalled == RPI_PICO_DEFCALL_DONTRUN) 131 | continue; 132 | 133 | if (timer[i].hasParam) 134 | (*(timer_callback_p)timer[i].callback)(timer[i].param); 135 | else 136 | (*(timer_callback)timer[i].callback)(); 137 | 138 | if (timer[i].toBeCalled == RPI_PICO_DEFCALL_RUNANDDEL) 139 | deleteTimer(i); 140 | } 141 | 142 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during ISR 143 | rp2040.resumeOtherCore(); 144 | 145 | } 146 | 147 | //////////////////////////////////////////////////////////////// 148 | 149 | // find the first available slot 150 | // return -1 if none found 151 | int RPI_PICO_ISR_Timer::findFirstFreeSlot() 152 | { 153 | // all slots are used 154 | if (numTimers >= RPI_PICO_MAX_TIMERS) 155 | { 156 | return -1; 157 | } 158 | 159 | // return the first slot with no callback (i.e. free) 160 | for (uint8_t i = 0; i < RPI_PICO_MAX_TIMERS; i++) 161 | { 162 | if (timer[i].callback == NULL) 163 | { 164 | return i; 165 | } 166 | } 167 | 168 | // no free slots found 169 | return -1; 170 | } 171 | 172 | //////////////////////////////////////////////////////////////// 173 | 174 | int RPI_PICO_ISR_Timer::setupTimer(const float& d, void* f, void* p, bool h, const unsigned& n) 175 | { 176 | int freeTimer; 177 | 178 | if (numTimers < 0) 179 | { 180 | init(); 181 | } 182 | 183 | freeTimer = findFirstFreeSlot(); 184 | 185 | if (freeTimer < 0) 186 | { 187 | return -1; 188 | } 189 | 190 | if (f == NULL) 191 | { 192 | return -1; 193 | } 194 | 195 | timer[freeTimer].delay = d; 196 | timer[freeTimer].callback = f; 197 | timer[freeTimer].param = p; 198 | timer[freeTimer].hasParam = h; 199 | timer[freeTimer].maxNumRuns = n; 200 | timer[freeTimer].enabled = true; 201 | timer[freeTimer].prev_millis = millis(); 202 | 203 | numTimers++; 204 | 205 | return freeTimer; 206 | } 207 | 208 | //////////////////////////////////////////////////////////////// 209 | 210 | int RPI_PICO_ISR_Timer::setTimer(const float& d, timer_callback f, const unsigned& n) 211 | { 212 | return setupTimer(d, (void *)f, NULL, false, n); 213 | } 214 | 215 | //////////////////////////////////////////////////////////////// 216 | 217 | int RPI_PICO_ISR_Timer::setTimer(const float& d, timer_callback_p f, void* p, const unsigned& n) 218 | { 219 | return setupTimer(d, (void *)f, p, true, n); 220 | } 221 | 222 | //////////////////////////////////////////////////////////////// 223 | 224 | int RPI_PICO_ISR_Timer::setInterval(const float& d, timer_callback f) 225 | { 226 | return setupTimer(d, (void *)f, NULL, false, RPI_PICO_RUN_FOREVER); 227 | } 228 | 229 | //////////////////////////////////////////////////////////////// 230 | 231 | int RPI_PICO_ISR_Timer::setInterval(const float& d, timer_callback_p f, void* p) 232 | { 233 | return setupTimer(d, (void *)f, p, true, RPI_PICO_RUN_FOREVER); 234 | } 235 | 236 | //////////////////////////////////////////////////////////////// 237 | 238 | int RPI_PICO_ISR_Timer::setTimeout(const float& d, timer_callback f) 239 | { 240 | return setupTimer(d, (void *)f, NULL, false, RPI_PICO_RUN_ONCE); 241 | } 242 | 243 | //////////////////////////////////////////////////////////////// 244 | 245 | int RPI_PICO_ISR_Timer::setTimeout(const float& d, timer_callback_p f, void* p) 246 | { 247 | return setupTimer(d, (void *)f, p, true, RPI_PICO_RUN_ONCE); 248 | } 249 | 250 | //////////////////////////////////////////////////////////////// 251 | 252 | bool RPI_PICO_ISR_Timer::changeInterval(const unsigned& numTimer, const float& d) 253 | { 254 | if (numTimer >= RPI_PICO_MAX_TIMERS) 255 | { 256 | return false; 257 | } 258 | 259 | // Updates interval of existing specified timer 260 | if (timer[numTimer].callback != NULL) 261 | { 262 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 263 | rp2040.idleOtherCore(); 264 | 265 | timer[numTimer].delay = d; 266 | timer[numTimer].prev_millis = millis(); 267 | 268 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 269 | rp2040.resumeOtherCore(); 270 | 271 | return true; 272 | } 273 | 274 | // false return for non-used numTimer, no callback 275 | return false; 276 | } 277 | 278 | //////////////////////////////////////////////////////////////// 279 | 280 | void RPI_PICO_ISR_Timer::deleteTimer(const unsigned& timerId) 281 | { 282 | if (timerId >= RPI_PICO_MAX_TIMERS) 283 | { 284 | return; 285 | } 286 | 287 | // nothing to delete if no timers are in use 288 | if (numTimers == 0) 289 | { 290 | return; 291 | } 292 | 293 | // don't decrease the number of timers if the specified slot is already empty 294 | if (timer[timerId].callback != NULL) 295 | { 296 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 297 | rp2040.idleOtherCore(); 298 | 299 | memset((void*) &timer[timerId], 0, sizeof (timer_t)); 300 | timer[timerId].prev_millis = millis(); 301 | 302 | // update number of timers 303 | numTimers--; 304 | 305 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 306 | rp2040.resumeOtherCore(); 307 | 308 | } 309 | } 310 | 311 | //////////////////////////////////////////////////////////////// 312 | 313 | // function contributed by code@rowansimms.com 314 | void RPI_PICO_ISR_Timer::restartTimer(const unsigned& numTimer) 315 | { 316 | if (numTimer >= RPI_PICO_MAX_TIMERS) 317 | { 318 | return; 319 | } 320 | 321 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 322 | rp2040.idleOtherCore(); 323 | 324 | timer[numTimer].prev_millis = millis(); 325 | 326 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 327 | rp2040.resumeOtherCore(); 328 | } 329 | 330 | //////////////////////////////////////////////////////////////// 331 | 332 | bool RPI_PICO_ISR_Timer::isEnabled(const unsigned& numTimer) 333 | { 334 | if (numTimer >= RPI_PICO_MAX_TIMERS) 335 | { 336 | return false; 337 | } 338 | 339 | return timer[numTimer].enabled; 340 | } 341 | 342 | //////////////////////////////////////////////////////////////// 343 | 344 | void RPI_PICO_ISR_Timer::enable(const unsigned& numTimer) 345 | { 346 | if (numTimer >= RPI_PICO_MAX_TIMERS) 347 | { 348 | return; 349 | } 350 | 351 | timer[numTimer].enabled = true; 352 | } 353 | 354 | //////////////////////////////////////////////////////////////// 355 | 356 | void RPI_PICO_ISR_Timer::disable(const unsigned& numTimer) 357 | { 358 | if (numTimer >= RPI_PICO_MAX_TIMERS) 359 | { 360 | return; 361 | } 362 | 363 | timer[numTimer].enabled = false; 364 | } 365 | 366 | //////////////////////////////////////////////////////////////// 367 | 368 | void RPI_PICO_ISR_Timer::enableAll() 369 | { 370 | // Enable all timers with a callback assigned (used) 371 | 372 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 373 | rp2040.idleOtherCore(); 374 | 375 | for (uint8_t i = 0; i < RPI_PICO_MAX_TIMERS; i++) 376 | { 377 | if (timer[i].callback != NULL && timer[i].numRuns == RPI_PICO_RUN_FOREVER) 378 | { 379 | timer[i].enabled = true; 380 | } 381 | } 382 | 383 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 384 | rp2040.resumeOtherCore(); 385 | } 386 | 387 | //////////////////////////////////////////////////////////////// 388 | 389 | void RPI_PICO_ISR_Timer::disableAll() 390 | { 391 | // Disable all timers with a callback assigned (used) 392 | 393 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 394 | rp2040.idleOtherCore(); 395 | 396 | for (uint8_t i = 0; i < RPI_PICO_MAX_TIMERS; i++) 397 | { 398 | if (timer[i].callback != NULL && timer[i].numRuns == RPI_PICO_RUN_FOREVER) 399 | { 400 | timer[i].enabled = false; 401 | } 402 | } 403 | 404 | // RPI_PICO is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars 405 | rp2040.resumeOtherCore(); 406 | 407 | } 408 | 409 | //////////////////////////////////////////////////////////////// 410 | 411 | void RPI_PICO_ISR_Timer::toggle(const unsigned& numTimer) 412 | { 413 | if (numTimer >= RPI_PICO_MAX_TIMERS) 414 | { 415 | return; 416 | } 417 | 418 | timer[numTimer].enabled = !timer[numTimer].enabled; 419 | } 420 | 421 | //////////////////////////////////////////////////////////////// 422 | 423 | unsigned RPI_PICO_ISR_Timer::getNumTimers() 424 | { 425 | return numTimers; 426 | } 427 | 428 | //////////////////////////////////////////////////////////////// 429 | 430 | #endif // ISR_TIMER_GENERIC_IMPL_H 431 | 432 | -------------------------------------------------------------------------------- /src/RPi_Pico_ISR_Timer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | RPi_Pico_ISR_Timer.h 3 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 10 | interrupts based on this timebase. It supports the following features: 11 | • A single 64-bit counter, incrementing once per microsecond 12 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 13 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 14 | 15 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 16 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 17 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 18 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 19 | This important feature is absolutely necessary for mission-critical tasks. 20 | 21 | Based on SimpleTimer - A timer library for Arduino. 22 | Author: mromani@ottotecnica.com 23 | Copyright (c) 2010 OTTOTECNICA Italy 24 | 25 | Based on BlynkTimer.h 26 | Author: Volodymyr Shymanskyy 27 | 28 | Version: 1.3.1 29 | 30 | Version Modified By Date Comments 31 | ------- ----------- ---------- ----------- 32 | 1.0.0 K Hoang 11/05/2021 Initial coding to support RP2040-based boards such as RASPBERRY_PI_PICO. etc. 33 | 1.0.1 K Hoang 18/05/2021 Update README and Packages' Patches to match core arduino-pico core v1.4.0 34 | 1.1.0 K Hoang 10/00/2021 Add support to new boards using the arduino-pico core 35 | 1.1.1 K Hoang 22/10/2021 Fix platform in library.json for PIO 36 | 1.2.0 K.Hoang 21/01/2022 Fix `multiple-definitions` linker error 37 | 1.3.0 K.Hoang 25/09/2022 Fix severe bug affecting time between the starts 38 | 1.3.1 K.Hoang 29/09/2022 Using float instead of ulong for interval 39 | *****************************************************************************************************************************/ 40 | 41 | #pragma once 42 | 43 | #ifndef ISR_TIMER_GENERIC_H 44 | #define ISR_TIMER_GENERIC_H 45 | 46 | #include "RPi_Pico_ISR_Timer.hpp" 47 | #include "RPi_Pico_ISR_Timer-Impl.h" 48 | 49 | #endif // ISR_TIMER_GENERIC_H 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/RPi_Pico_ISR_Timer.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | RPi_Pico_ISR_Timer.hpp 3 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 10 | interrupts based on this timebase. It supports the following features: 11 | • A single 64-bit counter, incrementing once per microsecond 12 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 13 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 14 | 15 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 16 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 17 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 18 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 19 | This important feature is absolutely necessary for mission-critical tasks. 20 | 21 | Based on SimpleTimer - A timer library for Arduino. 22 | Author: mromani@ottotecnica.com 23 | Copyright (c) 2010 OTTOTECNICA Italy 24 | 25 | Based on BlynkTimer.h 26 | Author: Volodymyr Shymanskyy 27 | 28 | Version: 1.3.1 29 | 30 | Version Modified By Date Comments 31 | ------- ----------- ---------- ----------- 32 | 1.0.0 K Hoang 11/05/2021 Initial coding to support RP2040-based boards such as RASPBERRY_PI_PICO. etc. 33 | 1.0.1 K Hoang 18/05/2021 Update README and Packages' Patches to match core arduino-pico core v1.4.0 34 | 1.1.0 K Hoang 10/00/2021 Add support to new boards using the arduino-pico core 35 | 1.1.1 K Hoang 22/10/2021 Fix platform in library.json for PIO 36 | 1.2.0 K.Hoang 21/01/2022 Fix `multiple-definitions` linker error 37 | 1.3.0 K.Hoang 25/09/2022 Fix severe bug affecting time between the starts 38 | 1.3.1 K.Hoang 29/09/2022 Using float instead of ulong for interval 39 | *****************************************************************************************************************************/ 40 | 41 | #pragma once 42 | 43 | #ifndef ISR_TIMER_GENERIC_HPP 44 | #define ISR_TIMER_GENERIC_HPP 45 | 46 | //////////////////////////////////////////////////////////////// 47 | 48 | #if ( defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_GENERIC_RP2040) ) && !defined(ARDUINO_ARCH_MBED) 49 | #if defined(USING_RPI_PICO_TIMER_INTERRUPT) 50 | #undef USING_RPI_PICO_TIMER_INTERRUPT 51 | #endif 52 | #define USING_RPI_PICO_TIMER_INTERRUPT true 53 | #else 54 | #error This code is intended to run on the non-mbed RP2040 arduino-pico platform! Please check your Tools->Board setting. 55 | #endif 56 | 57 | //////////////////////////////////////////////////////////////// 58 | 59 | #ifndef RPI_PICO_TIMER_INTERRUPT_VERSION 60 | #define RPI_PICO_TIMER_INTERRUPT_VERSION "RPi_Pico_TimerInterrupt v1.3.1" 61 | 62 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_MAJOR 1 63 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_MINOR 3 64 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_PATCH 1 65 | 66 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_INT 1003001 67 | #endif 68 | 69 | //////////////////////////////////////////////////////////////// 70 | 71 | #include "TimerInterrupt_Generic_Debug.h" 72 | 73 | #include 74 | 75 | #include 76 | 77 | #include "pico/multicore.h" 78 | 79 | #if defined(ARDUINO) 80 | #if ARDUINO >= 100 81 | #include 82 | #else 83 | #include 84 | #endif 85 | #endif 86 | 87 | #define FLAG_VALUE 0xDEADBEEF 88 | 89 | #define RPI_PICO_ISR_Timer RPI_PICO_ISRTimer 90 | 91 | typedef void (*timer_callback)(); 92 | typedef void (*timer_callback_p)(void *); 93 | 94 | //////////////////////////////////////////////////////////////// 95 | 96 | class RPI_PICO_ISR_Timer 97 | { 98 | public: 99 | // maximum number of timers 100 | #define RPI_PICO_MAX_TIMERS 16 101 | #define RPI_PICO_RUN_FOREVER 0 102 | #define RPI_PICO_RUN_ONCE 1 103 | 104 | // constructor 105 | RPI_PICO_ISR_Timer(); 106 | 107 | void init(); 108 | 109 | // this function must be called inside loop() 110 | void run(); 111 | 112 | // Timer will call function 'f' every 'd' milliseconds forever 113 | // returns the timer number (numTimer) on success or 114 | // -1 on failure (f == NULL) or no free timers 115 | int setInterval(const float& d, timer_callback f); 116 | 117 | // Timer will call function 'f' with parameter 'p' every 'd' milliseconds forever 118 | // returns the timer number (numTimer) on success or 119 | // -1 on failure (f == NULL) or no free timers 120 | int setInterval(const float& d, timer_callback_p f, void* p); 121 | 122 | // Timer will call function 'f' after 'd' milliseconds one time 123 | // returns the timer number (numTimer) on success or 124 | // -1 on failure (f == NULL) or no free timers 125 | int setTimeout(const float& d, timer_callback f); 126 | 127 | // Timer will call function 'f' with parameter 'p' after 'd' milliseconds one time 128 | // returns the timer number (numTimer) on success or 129 | // -1 on failure (f == NULL) or no free timers 130 | int setTimeout(const float& d, timer_callback_p f, void* p); 131 | 132 | // Timer will call function 'f' every 'd' milliseconds 'n' times 133 | // returns the timer number (numTimer) on success or 134 | // -1 on failure (f == NULL) or no free timers 135 | int setTimer(const float& d, timer_callback f, const unsigned& n); 136 | 137 | // Timer will call function 'f' with parameter 'p' every 'd' milliseconds 'n' times 138 | // returns the timer number (numTimer) on success or 139 | // -1 on failure (f == NULL) or no free timers 140 | int setTimer(const float& d, timer_callback_p f, void* p, const unsigned& n); 141 | 142 | // updates interval of the specified timer 143 | bool changeInterval(const unsigned& numTimer, const float& d); 144 | 145 | // destroy the specified timer 146 | void deleteTimer(const unsigned& numTimer); 147 | 148 | // restart the specified timer 149 | void restartTimer(const unsigned& numTimer); 150 | 151 | // returns true if the specified timer is enabled 152 | bool isEnabled(const unsigned& numTimer); 153 | 154 | // enables the specified timer 155 | void enable(const unsigned& numTimer); 156 | 157 | // disables the specified timer 158 | void disable(const unsigned& numTimer); 159 | 160 | // enables all timers 161 | void enableAll(); 162 | 163 | // disables all timers 164 | void disableAll(); 165 | 166 | // enables the specified timer if it's currently disabled, and vice-versa 167 | void toggle(const unsigned& numTimer); 168 | 169 | // returns the number of used timers 170 | unsigned getNumTimers(); 171 | 172 | // returns the number of available timers 173 | unsigned getNumAvailableTimers() 174 | { 175 | return RPI_PICO_MAX_TIMERS - numTimers; 176 | }; 177 | 178 | private: 179 | // deferred call constants 180 | #define RPI_PICO_DEFCALL_DONTRUN 0 // don't call the callback function 181 | #define RPI_PICO_DEFCALL_RUNONLY 1 // call the callback function but don't delete the timer 182 | #define RPI_PICO_DEFCALL_RUNANDDEL 2 // call the callback function and delete the timer 183 | 184 | // low level function to initialize and enable a new timer 185 | // returns the timer number (numTimer) on success or 186 | // -1 on failure (f == NULL) or no free timers 187 | int setupTimer(const float& d, void* f, void* p, bool h, const unsigned& n); 188 | 189 | // find the first available slot 190 | int findFirstFreeSlot(); 191 | 192 | typedef struct 193 | { 194 | unsigned long prev_millis; // value returned by the millis() function in the previous run() call 195 | void* callback; // pointer to the callback function 196 | void* param; // function parameter 197 | bool hasParam; // true if callback takes a parameter 198 | float delay; // delay value 199 | unsigned maxNumRuns; // number of runs to be executed 200 | unsigned numRuns; // number of executed runs 201 | bool enabled; // true if enabled 202 | unsigned toBeCalled; // deferred function call (sort of) - N.B.: only used in run() 203 | } timer_t; 204 | 205 | volatile timer_t timer[RPI_PICO_MAX_TIMERS]; 206 | 207 | // actual number of timers in use (-1 means uninitialized) 208 | volatile int numTimers; 209 | }; 210 | 211 | //////////////////////////////////////////////////////////////// 212 | 213 | #endif // ISR_TIMER_GENERIC_HPP 214 | 215 | 216 | -------------------------------------------------------------------------------- /src/RPi_Pico_TimerInterrupt.h: -------------------------------------------------------------------------------- 1 | 2 | /**************************************************************************************************************************** 3 | RPi_Pico_TimerInterrupt.h 4 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 5 | Written by Khoi Hoang 6 | 7 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 8 | Licensed under MIT license 9 | 10 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 11 | interrupts based on this timebase. It supports the following features: 12 | • A single 64-bit counter, incrementing once per microsecond 13 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 14 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 15 | 16 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 17 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 18 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 19 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 20 | This important feature is absolutely necessary for mission-critical tasks. 21 | 22 | Based on SimpleTimer - A timer library for Arduino. 23 | Author: mromani@ottotecnica.com 24 | Copyright (c) 2010 OTTOTECNICA Italy 25 | 26 | Based on BlynkTimer.h 27 | Author: Volodymyr Shymanskyy 28 | 29 | Version: 1.3.1 30 | 31 | Version Modified By Date Comments 32 | ------- ----------- ---------- ----------- 33 | 1.0.0 K Hoang 11/05/2021 Initial coding to support RP2040-based boards such as RASPBERRY_PI_PICO. etc. 34 | 1.0.1 K Hoang 18/05/2021 Update README and Packages' Patches to match core arduino-pico core v1.4.0 35 | 1.1.0 K Hoang 10/00/2021 Add support to new boards using the arduino-pico core 36 | 1.1.1 K Hoang 22/10/2021 Fix platform in library.json for PIO 37 | 1.2.0 K.Hoang 21/01/2022 Fix `multiple-definitions` linker error 38 | 1.3.0 K.Hoang 25/09/2022 Fix severe bug affecting time between the starts 39 | 1.3.1 K.Hoang 29/09/2022 Using float instead of ulong for interval 40 | *****************************************************************************************************************************/ 41 | 42 | #pragma once 43 | 44 | #ifndef RPI_PICO_TIMERINTERRUPT_H 45 | #define RPI_PICO_TIMERINTERRUPT_H 46 | 47 | #if ( defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_GENERIC_RP2040) ) && !defined(ARDUINO_ARCH_MBED) 48 | #if defined(USING_RPI_PICO_TIMER_INTERRUPT) 49 | #undef USING_RPI_PICO_TIMER_INTERRUPT 50 | #endif 51 | #define USING_RPI_PICO_TIMER_INTERRUPT true 52 | #else 53 | #error This code is intended to run on the non-mbed RP2040 arduino-pico platform! Please check your Tools->Board setting. 54 | #endif 55 | 56 | //////////////////////////////////////////////////////////////// 57 | 58 | #ifndef RPI_PICO_TIMER_INTERRUPT_VERSION 59 | #define RPI_PICO_TIMER_INTERRUPT_VERSION "RPi_Pico_TimerInterrupt v1.3.1" 60 | 61 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_MAJOR 1 62 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_MINOR 3 63 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_PATCH 1 64 | 65 | #define RPI_PICO_TIMER_INTERRUPT_VERSION_INT 1003001 66 | #endif 67 | 68 | //////////////////////////////////////////////////////////////// 69 | 70 | #ifndef TIMER_INTERRUPT_DEBUG 71 | #define TIMER_INTERRUPT_DEBUG 0 72 | #endif 73 | 74 | //////////////////////////////////////////////////////////////// 75 | 76 | #include "Arduino.h" 77 | 78 | #include 79 | #include "pico/stdlib.h" 80 | #include "hardware/timer.h" 81 | #include "hardware/irq.h" 82 | 83 | #include "TimerInterrupt_Generic_Debug.h" 84 | 85 | //////////////////////////////////////////////////////////////// 86 | 87 | /* 88 | To enable an alarm: 89 | • Enable the interrupt at the timer with a write to the appropriate alarm bit in INTE: i.e. (1 << 0) for ALARM0 90 | • Enable the appropriate timer interrupt at the processor (see Section 2.3.2) 91 | • Write the time you would like the interrupt to fire to ALARM0 (i.e. the current value in TIMERAWL plus your desired 92 | alarm time in microseconds). Writing the time to the ALARM register sets the ARMED bit as a side effect. 93 | Once the alarm has fired, the ARMED bit will be set to 0 . To clear the latched interrupt, write a 1 to the appropriate bit in 94 | INTR. 95 | */ 96 | 97 | 98 | class RPI_PICO_TimerInterrupt; 99 | 100 | typedef RPI_PICO_TimerInterrupt RPI_PICO_Timer; 101 | 102 | // We can use many timers here 103 | #define MAX_RPI_PICO_NUM_TIMERS 4 104 | 105 | typedef bool (*pico_timer_callback) (struct repeating_timer *t); 106 | 107 | //////////////////////////////////////////////////////////////// 108 | 109 | class RPI_PICO_TimerInterrupt 110 | { 111 | private: 112 | 113 | uint8_t _timerNo; 114 | 115 | pico_timer_callback _callback; // pointer to the callback function 116 | float _frequency; // Timer frequency 117 | int64_t _timerCount; // count to activate timer, in us 118 | 119 | struct repeating_timer _timer; 120 | 121 | public: 122 | 123 | RPI_PICO_TimerInterrupt(uint8_t timerNo) 124 | { 125 | _timerNo = timerNo; 126 | _callback = NULL; 127 | }; 128 | 129 | //////////////////////////////////////////////////////////////// 130 | 131 | #define TIM_CLOCK_FREQ ( (float) 1000000.0f ) 132 | 133 | // frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely 134 | // No params and duration now. To be added in the future by adding similar functions here 135 | bool setFrequency(const float& frequency, pico_timer_callback callback) 136 | { 137 | if (_timerNo < MAX_RPI_PICO_NUM_TIMERS) 138 | { 139 | if ( (frequency == 0.0f) || (frequency > 100000.0f) || (callback == NULL) ) 140 | { 141 | TISR_LOGERROR(F("Error. frequency == 0, higher than 100KHz or callback == NULL ")); 142 | 143 | return false; 144 | } 145 | 146 | // select timer frequency is 1MHz for better accuracy. We don't use 16-bit prescaler for now. 147 | // Will use later if very low frequency is needed. 148 | _frequency = frequency; 149 | _timerCount = (int64_t) (TIM_CLOCK_FREQ / frequency); 150 | 151 | TISR_LOGWARN5(F("_timerNo = "), _timerNo, F(", Clock (Hz) = "), TIM_CLOCK_FREQ, F(", _fre (Hz) = "), _frequency); 152 | TISR_LOGWARN3(F("_count = "), (uint32_t) (_timerCount >> 32), F("-"), (uint32_t) (_timerCount)); 153 | 154 | _callback = callback; 155 | 156 | // static bool add_repeating_timer_us(int64_t delay_us, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out); 157 | // static bool add_repeating_timer_ms(int64_t delay_ms, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out); 158 | // bool cancel_repeating_timer (repeating_timer_t *timer); 159 | ////////////////////////////////////////////////////////////////////////// 160 | // Important Notes 161 | // delay_ms the repeat delay in milliseconds; if >0 then this is the delay between one callback ending and the next 162 | // starting; if <0 then this is the negative of the time between the starts of the callbacks. 163 | // The value of 0 is treated as 1 microsecond 164 | ////////////////////////////////////////////////////////////////////////// 165 | cancel_repeating_timer(&_timer); 166 | 167 | // Use negative value to select time between the starts of the callbacks 168 | add_repeating_timer_us(-(_timerCount), _callback, NULL, &_timer); 169 | 170 | TISR_LOGWARN1(F("add_repeating_timer_us between starts = "), _timerCount); 171 | 172 | return true; 173 | } 174 | else 175 | { 176 | TISR_LOGERROR(F("Error. Timer must be 0-3")); 177 | 178 | return false; 179 | } 180 | } 181 | 182 | //////////////////////////////////////////////////////////////// 183 | 184 | // interval (in microseconds) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely 185 | // No params and duration now. To be added in the future by adding similar functions here 186 | bool setInterval(const float& interval, pico_timer_callback callback) 187 | { 188 | return setFrequency((float) (1000000.0f / interval), callback); 189 | } 190 | 191 | //////////////////////////////////////////////////////////////// 192 | 193 | bool attachInterrupt(const float& frequency, pico_timer_callback callback) 194 | { 195 | return setFrequency(frequency, callback); 196 | } 197 | 198 | //////////////////////////////////////////////////////////////// 199 | 200 | // interval (in microseconds) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely 201 | // No params and duration now. To be added in the future by adding similar functions here 202 | bool attachInterruptInterval(const float& interval, pico_timer_callback callback) 203 | { 204 | return setFrequency( (float) ( 1000000.0f / interval), callback); 205 | } 206 | 207 | //////////////////////////////////////////////////////////////// 208 | 209 | void detachInterrupt() 210 | { 211 | cancel_repeating_timer(&_timer); 212 | } 213 | 214 | //////////////////////////////////////////////////////////////// 215 | 216 | void disableTimer() 217 | { 218 | cancel_repeating_timer(&_timer); 219 | } 220 | 221 | //////////////////////////////////////////////////////////////// 222 | 223 | // Duration (in microseconds). Duration = 0 or not specified => run indefinitely 224 | void reattachInterrupt() 225 | { 226 | add_repeating_timer_us(-(_timerCount), _callback, NULL, &_timer); 227 | } 228 | 229 | //////////////////////////////////////////////////////////////// 230 | 231 | // Duration (in microseconds). Duration = 0 or not specified => run indefinitely 232 | void enableTimer() 233 | { 234 | add_repeating_timer_us(-(_timerCount), _callback, NULL, &_timer); 235 | } 236 | 237 | //////////////////////////////////////////////////////////////// 238 | 239 | // Just stop clock source, clear the count 240 | void stopTimer() 241 | { 242 | cancel_repeating_timer(&_timer); 243 | } 244 | 245 | //////////////////////////////////////////////////////////////// 246 | 247 | // Just reconnect clock source, start current count from 0 248 | void restartTimer() 249 | { 250 | cancel_repeating_timer(&_timer); 251 | add_repeating_timer_us(-(_timerCount), _callback, NULL, &_timer); 252 | } 253 | 254 | //////////////////////////////////////////////////////////////// 255 | 256 | int8_t getTimer() __attribute__((always_inline)) 257 | { 258 | return _timerNo; 259 | }; 260 | 261 | //////////////////////////////////////////////////////////////// 262 | 263 | }; // class RPI_PICO_TimerInterrupt 264 | 265 | #endif // RPI_PICO_TIMERINTERRUPT_H 266 | 267 | -------------------------------------------------------------------------------- /src/TimerInterrupt_Generic_Debug.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************************************** 2 | TimerInterrupt_Generic_Debug.h 3 | For RP2040-based boards such as RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040. 4 | Written by Khoi Hoang 5 | 6 | Built by Khoi Hoang https://github.com/khoih-prog/RPI_PICO_TimerInterrupt 7 | Licensed under MIT license 8 | 9 | The RPI_PICO system timer peripheral provides a global microsecond timebase for the system, and generates 10 | interrupts based on this timebase. It supports the following features: 11 | • A single 64-bit counter, incrementing once per microsecond 12 | • This counter can be read from a pair of latching registers, for race-free reads over a 32-bit bus. 13 | • Four alarms: match on the lower 32 bits of counter, IRQ on match: TIMER_IRQ_0-TIMER_IRQ_3 14 | 15 | Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by 16 | unsigned long miliseconds), you just consume only one RPI_PICO timer and avoid conflicting with other cores' tasks. 17 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers 18 | Therefore, their executions are not blocked by bad-behaving functions / tasks. 19 | This important feature is absolutely necessary for mission-critical tasks. 20 | 21 | Based on SimpleTimer - A timer library for Arduino. 22 | Author: mromani@ottotecnica.com 23 | Copyright (c) 2010 OTTOTECNICA Italy 24 | 25 | Based on BlynkTimer.h 26 | Author: Volodymyr Shymanskyy 27 | 28 | Version: 1.3.1 29 | 30 | Version Modified By Date Comments 31 | ------- ----------- ---------- ----------- 32 | 1.0.0 K Hoang 11/05/2021 Initial coding to support RP2040-based boards such as RASPBERRY_PI_PICO. etc. 33 | 1.0.1 K Hoang 18/05/2021 Update README and Packages' Patches to match core arduino-pico core v1.4.0 34 | 1.1.0 K Hoang 10/00/2021 Add support to new boards using the arduino-pico core 35 | 1.1.1 K Hoang 22/10/2021 Fix platform in library.json for PIO 36 | 1.2.0 K.Hoang 21/01/2022 Fix `multiple-definitions` linker error 37 | 1.3.0 K.Hoang 25/09/2022 Fix severe bug affecting time between the starts 38 | 1.3.1 K.Hoang 29/09/2022 Using float instead of ulong for interval 39 | *****************************************************************************************************************************/ 40 | 41 | #pragma once 42 | 43 | #ifndef TIMERINTERRUPT_GENERIC_DEBUG_H 44 | #define TIMERINTERRUPT_GENERIC_DEBUG_H 45 | 46 | //////////////////////////////////////////////////////////////// 47 | 48 | #ifdef TIMERINTERRUPT_DEBUG_PORT 49 | #define TISR_DBG_PORT TIMERINTERRUPT_DEBUG_PORT 50 | #else 51 | #define TISR_DBG_PORT Serial 52 | #endif 53 | 54 | //////////////////////////////////////////////////////////////// 55 | 56 | // Change _TIMERINTERRUPT_LOGLEVEL_ to set tracing and logging verbosity 57 | // 0: DISABLED: no logging 58 | // 1: ERROR: errors 59 | // 2: WARN: errors and warnings 60 | // 3: INFO: errors, warnings and informational (default) 61 | // 4: DEBUG: errors, warnings, informational and debug 62 | 63 | #ifndef _TIMERINTERRUPT_LOGLEVEL_ 64 | #define _TIMERINTERRUPT_LOGLEVEL_ 1 65 | #endif 66 | 67 | ////////////////////////////////////////// 68 | 69 | const char TISR_MARK[] = "[TISR] "; 70 | const char TISR_SP[] = " "; 71 | 72 | #define TISR_PRINT TISR_DBG_PORT.print 73 | #define TISR_PRINTLN TISR_DBG_PORT.println 74 | 75 | #define TISR_PRINT_MARK TISR_PRINT(TISR_MARK) 76 | #define TISR_PRINT_SP TISR_PRINT(TISR_SP) 77 | 78 | /////////////////////////////////////// 79 | 80 | #define TISR_LOGERROR(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 81 | #define TISR_LOGERROR0(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT(x); } 82 | #define TISR_LOGERROR1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 83 | #define TISR_LOGERROR2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 84 | #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); } 85 | #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); } 86 | 87 | /////////////////////////////////////// 88 | 89 | #define TISR_LOGWARN(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 90 | #define TISR_LOGWARN0(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT(x); } 91 | #define TISR_LOGWARN1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 92 | #define TISR_LOGWARN2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 93 | #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); } 94 | #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); } 95 | 96 | /////////////////////////////////////// 97 | 98 | #define TISR_LOGINFO(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 99 | #define TISR_LOGINFO0(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT(x); } 100 | #define TISR_LOGINFO1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 101 | #define TISR_LOGINFO2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 102 | #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); } 103 | #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); } 104 | 105 | /////////////////////////////////////// 106 | 107 | #define TISR_LOGDEBUG(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINTLN(x); } 108 | #define TISR_LOGDEBUG0(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT(x); } 109 | #define TISR_LOGDEBUG1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINTLN(y); } 110 | #define TISR_LOGDEBUG2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_PRINT_MARK; TISR_PRINT(x); TISR_PRINT(y); TISR_PRINTLN(z); } 111 | #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); } 112 | #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); } 113 | 114 | /////////////////////////////////////// 115 | 116 | #endif //TIMERINTERRUPT_GENERIC_DEBUG_H 117 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------