diff --git a/.bazelrc b/.bazelrc
index a94ccd3de..96b4eca24 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,7 +1,3 @@
-# Required for new toolchain resolution API.
-build --incompatible_enable_cc_toolchain_resolution
-build --@rules_cc//cc/toolchains:experimental_enable_rule_based_toolchains
-
# Silence all C/C++ warnings in external code.
common --per_file_copt=external/.*@-w
common --host_per_file_copt=external/.*@-w
diff --git a/.github/workflows/bazel_build.yml b/.github/workflows/bazel_build.yml
new file mode 100644
index 000000000..af053b6f2
--- /dev/null
+++ b/.github/workflows/bazel_build.yml
@@ -0,0 +1,76 @@
+name: Bazel presubmit checks
+
+# Disable build in zephyr repository
+# on:
+# push:
+# pull_request:
+
+jobs:
+ bazel-build-check:
+ strategy:
+ matrix:
+ # TODO: Windows is currently broken.
+ os: [ubuntu-latest, macos-latest]
+ fail-fast: false
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Get Bazel
+ uses: bazel-contrib/setup-bazel@0.9.0
+ with:
+ # Avoid downloading Bazel every time.
+ bazelisk-cache: true
+ # Store build cache per workflow.
+ disk-cache: ${{ github.workflow }}
+ # Share repository cache between workflows.
+ repository-cache: true
+ # Only needed to drive the presbumit scripts.
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.10'
+ - name: Fetch latest Picotool
+ uses: actions/checkout@v4
+ with:
+ repository: raspberrypi/picotool
+ ref: develop
+ fetch-depth: 0
+ path: lib/picotool
+ - name: Full Bazel build with develop Picotool
+ run: python3 tools/run_all_bazel_checks.py --program=build --picotool-dir=lib/picotool
+ # Checks that the current BCR-requested version of Picotool builds.
+ - name: Bazel Picotool backwards compatibility
+ run: bazel build @picotool//:picotool
+ other-bazel-checks:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Get Bazel
+ uses: bazel-contrib/setup-bazel@0.9.0
+ with:
+ # Avoid downloading Bazel every time.
+ bazelisk-cache: true
+ # Store build cache per workflow.
+ disk-cache: ${{ github.workflow }}
+ # Share repository cache between workflows.
+ repository-cache: true
+ # Only needed to drive the presbumit scripts.
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.10'
+ - name: Fetch latest Picotool
+ uses: actions/checkout@v4
+ with:
+ repository: raspberrypi/picotool
+ ref: develop
+ fetch-depth: 0
+ path: lib/picotool
+ - name: Other Bazel checks
+ run: python3 tools/run_all_bazel_checks.py --program=other --picotool-dir=lib/picotool
diff --git a/.github/workflows/choco_packages.config b/.github/workflows/choco_packages.config
index b2d3db147..f7885c9fc 100644
--- a/.github/workflows/choco_packages.config
+++ b/.github/workflows/choco_packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml
index 45fada86f..28ee68bd6 100644
--- a/.github/workflows/cmake.yml
+++ b/.github/workflows/cmake.yml
@@ -23,7 +23,7 @@ jobs:
mkdir -p "${{ github.workspace }}"
- name: Checkout repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init
diff --git a/.github/workflows/macOS.yml b/.github/workflows/macOS.yml
index 35cb98096..42282672f 100644
--- a/.github/workflows/macOS.yml
+++ b/.github/workflows/macOS.yml
@@ -9,7 +9,7 @@ on:
jobs:
build:
- runs-on: macos-12
+ runs-on: macos-latest
steps:
- name: Clean workspace
run: |
@@ -17,7 +17,7 @@ jobs:
rm -rf "${{ github.workspace }}"
mkdir -p "${{ github.workspace }}"
- name: Checkout repo
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init
- name: Install dependencies
diff --git a/.github/workflows/multi-gcc.yml b/.github/workflows/multi-gcc.yml
index 3f41cd98a..886109d2e 100644
--- a/.github/workflows/multi-gcc.yml
+++ b/.github/workflows/multi-gcc.yml
@@ -20,7 +20,7 @@ jobs:
mkdir -p "${{ github.workspace }}"
- name: Checkout repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init
diff --git a/.github/workflows/scripts/generate_multi_gcc_workflow.py b/.github/workflows/scripts/generate_multi_gcc_workflow.py
index 19bf2339d..ac10b8b2c 100755
--- a/.github/workflows/scripts/generate_multi_gcc_workflow.py
+++ b/.github/workflows/scripts/generate_multi_gcc_workflow.py
@@ -55,7 +55,7 @@
mkdir -p "${{ github.workspace }}"
- name: Checkout repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 8ed2a033f..ea4394af5 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -17,15 +17,14 @@ jobs:
echo "Cleaning up previous run"
rm -rf "${{ github.workspace }}/pico-sdk"
- name: Checkout repo
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init
- name: Install dependencies
run: choco install .github/workflows/choco_packages.config
- name: Build Project
- # bash required otherwise this mysteriously (no error) fails at "Generating cyw43_bus_pio_spi.pio.h"
- shell: bash
+ shell: pwsh
run: |
mkdir build
cd build
diff --git a/.gitignore b/.gitignore
index a893fc633..8f7a3f577 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
.idea
.vscode
cmake-*
+.cache
.DS_Store
build
build-*
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1bee20540..aa09dfa2f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -22,4 +22,4 @@ If you are contributing new or updated code please match the existing code style
### Licensing
-Code in this repository is lisensed under the [BSD-3 License](LICENSE.TXT). By contributing content to this repository you are agreeing to place your contributions under this licence.
+Code in this repository is licensed under the [BSD-3 License](LICENSE.TXT). By contributing content to this repository you are agreeing to place your contributions under this license.
diff --git a/ChangeLog.zephyr.md b/ChangeLog.zephyr.md
index ebb56aa66..ddd871637 100644
--- a/ChangeLog.zephyr.md
+++ b/ChangeLog.zephyr.md
@@ -3,6 +3,8 @@
Need to take care to not break these changes when updating pico-sdk.
## Patch List:
+ - [#10] pico-sdk: Disabling bazel build
+ - .github/workflows/bazel_build.yml
- [#9] pico-sdk: Disabling sanity check the IRQ status
- src/rp2_common/hardware_gpio/gpio.c
- [#8] pico-sdk: pico_platform_compiler: Do not redefine `__weak`
diff --git a/MODULE.bazel b/MODULE.bazel
index 2094c3b8e..9cdcce3b2 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -1,31 +1,24 @@
module(
name = "pico-sdk",
- version = "2.0.0",
+ version = "2.1.0",
)
bazel_dep(name = "platforms", version = "0.0.9")
bazel_dep(name = "bazel_skylib", version = "1.6.1")
-bazel_dep(name = "rules_python", version = "0.22.1")
-bazel_dep(name = "picotool", version = "2.0.0")
+bazel_dep(name = "rules_python", version = "0.36.0")
+bazel_dep(name = "picotool", version = "2.1.0")
+bazel_dep(name = "rules_cc", version = "0.0.10")
-# Note: rules_cc is special-cased repository; a dependency on rules_cc in a
-# module will not ensure that the root Bazel module has that same version of
-# rules_cc. For that reason, this primarily acts as a FYI. You'll still need
-# to explicitly list this dependency in your own project's MODULE.bazel file.
-bazel_dep(name = "rules_cc", version = "0.0.9")
+http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-# rules_cc v0.0.10 is not yet cut, so manually pull in the desired version.
-# This does not apply to dependent projects, so it needs to be copied to your
-# project's MODULE.bazel too.
-archive_override(
- module_name = "rules_cc",
- integrity = "sha256-zdQo/pQWKdIAPKSflBxOSWZNwCbc86T7SechKZo/3Xw=",
- strip_prefix = "rules_cc-1acf5213b6170f1f0133e273cb85ede0e732048f",
- urls = "https://github.com/bazelbuild/rules_cc/archive/1acf5213b6170f1f0133e273cb85ede0e732048f.tar.gz",
+http_archive(
+ name = "arm_gcc_linux-aarch64",
+ build_file = "//bazel/toolchain:gcc_arm_none_eabi.BUILD",
+ sha256 = "8fd8b4a0a8d44ab2e195ccfbeef42223dfb3ede29d80f14dcf2183c34b8d199a",
+ strip_prefix = "arm-gnu-toolchain-13.2.Rel1-aarch64-arm-none-eabi",
+ url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-aarch64-arm-none-eabi.tar.xz",
)
-http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
http_archive(
name = "arm_gcc_linux-x86_64",
build_file = "//bazel/toolchain:gcc_arm_none_eabi.BUILD",
@@ -61,73 +54,73 @@ http_archive(
http_archive(
name = "clang_linux-x86_64",
build_file = "//bazel/toolchain:clang.BUILD",
- sha256 = "e12ee0db9226f5b4a4400c5eb2c0f757d7056181b651622b5453acb00105fd87",
+ sha256 = "6c599d1aba568236064c340d7813324849896d5a4e2f3fd8225a8c31bfcbf884",
type = "zip",
- url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64/+/git_revision:248c53429427034f45705af60d47f3b1090c4799",
+ url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64/+/git_revision:2b0a708f41dd6291ee744704d43febc975e3d026",
)
http_archive(
name = "clang_win-x86_64",
build_file = "//bazel/toolchain:clang.BUILD",
- sha256 = "8c41e8b507f4dfede80842f98a716cac209f552064088fa1b7f4c64a1e547534",
+ sha256 = "f49ba4123ee3958f2b47289d017a5b3f1ca01f82dd7a2168c45412c18101fd13",
type = "zip",
# Windows doesn't like `:` in the produced filename, so replace it with `%3A`.
- url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/windows-amd64/+/git_revision:248c53429427034f45705af60d47f3b1090c4799".replace("git_revision:", "git_revision%3A"),
+ url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/windows-amd64/+/git_revision:2b0a708f41dd6291ee744704d43febc975e3d026".replace("git_revision:", "git_revision%3A"),
)
http_archive(
name = "clang_mac-x86_64",
build_file = "//bazel/toolchain:clang.BUILD",
- sha256 = "1d92f52609d3c1e958fd56f5e9a68ab99b2042ddcc6e90a5eb5009cf7ac4897d",
+ sha256 = "d3516f2eb4c12d17ae77ee84c9226fbea581d4fb806910ceac4717d5adfcf748",
type = "zip",
- url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/mac-amd64/+/git_revision:248c53429427034f45705af60d47f3b1090c4799",
+ url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/mac-amd64/+/git_revision:2b0a708f41dd6291ee744704d43febc975e3d026",
)
http_archive(
name = "clang_mac-aarch64",
build_file = "//bazel/toolchain:clang.BUILD",
- sha256 = "53184680db7e0043a8fba1556c7644b8f5e6c8cdffa4436a92a8e8adb0f45b8d",
+ sha256 = "68e551f41c7e9473063b09819f6ab8ec6e7e53677f4078189656cb14dc52984b",
type = "zip",
- url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/mac-arm64/+/git_revision:248c53429427034f45705af60d47f3b1090c4799",
+ url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/mac-arm64/+/git_revision:2b0a708f41dd6291ee744704d43febc975e3d026",
)
+new_git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
+
# TODO: Provide tinyusb as a proper Bazel module.
-http_archive(
+new_git_repository(
name = "tinyusb",
build_file = "//src/rp2_common/tinyusb:tinyusb.BUILD",
- sha256 = "d64728aef58b80d5ce3747cad133f520da46e2b7ea3aadfda0e981aba6b658b3",
- strip_prefix = "tinyusb-4232642899362fa5e9cf0dc59bad6f1f6d32c563",
- url = "https://github.com/hathach/tinyusb/archive/4232642899362fa5e9cf0dc59bad6f1f6d32c563.tar.gz",
+ commit = "5217cee5de4cd555018da90f9f1bcc87fb1c1d3a", # keep-in-sync-with-submodule: lib/tinyusb
+ remote = "https://github.com/hathach/tinyusb.git",
)
# TODO: Provide btstack as a proper Bazel module.
-http_archive(
+new_git_repository(
name = "btstack",
build_file = "//src/rp2_common/pico_btstack:btstack.BUILD",
- sha256 = "64e86d9cf82b346e743fe1d4818b9380712b17abdb3f2c3524e92464b5ef3d19",
- strip_prefix = "btstack-2b49e57bd1fae85ac32ac1f41cdb7c794de335f6",
- url = "https://github.com/bluekitchen/btstack/archive/2b49e57bd1fae85ac32ac1f41cdb7c794de335f6.tar.gz",
+ commit = "2b49e57bd1fae85ac32ac1f41cdb7c794de335f6", # keep-in-sync-with-submodule: lib/btstack
+ remote = "https://github.com/bluekitchen/btstack.git",
)
-# TODO: Provide btstack as a proper Bazel module.
-http_archive(
+# TODO: Provide cyw43-driver as a proper Bazel module.
+new_git_repository(
name = "cyw43-driver",
build_file = "//src/rp2_common/pico_cyw43_driver:cyw43-driver.BUILD",
- sha256 = "0fcc7707fef95dd562d5572604713266613a27caeeae2f10afeccee9592a53ce",
- strip_prefix = "cyw43-driver-faf36381bad1f668a30172b6336c9a970966ef4c",
- url = "https://github.com/georgerobotics/cyw43-driver/archive/faf36381bad1f668a30172b6336c9a970966ef4c.tar.gz",
+ commit = "cf924bb04c8984675ca0fc2178f082e404e048c3", # keep-in-sync-with-submodule: lib/cyw43-driver
+ remote = "https://github.com/georgerobotics/cyw43-driver.git",
)
# TODO: Provide lwip as a proper Bazel module.
-http_archive(
+new_git_repository(
name = "lwip",
build_file = "//src/rp2_common/pico_lwip:lwip.BUILD",
- sha256 = "72856d557f72911cf6826ef745c23c54822df83a474557823241164a1d1361aa",
- strip_prefix = "lwip-0a0452b2c39bdd91e252aef045c115f88f6ca773",
- url = "https://github.com/lwip-tcpip/lwip/archive/0a0452b2c39bdd91e252aef045c115f88f6ca773.tar.gz",
+ commit = "0a0452b2c39bdd91e252aef045c115f88f6ca773", # keep-in-sync-with-submodule: lib/lwip
+ remote = "https://github.com/lwip-tcpip/lwip.git",
)
register_toolchains(
+ "//bazel/toolchain:linux-aarch64-rp2040",
+ "//bazel/toolchain:linux-aarch64-rp2350",
"//bazel/toolchain:linux-x86_64-rp2040",
"//bazel/toolchain:linux-x86_64-rp2350",
"//bazel/toolchain:win-x86_64-rp2040",
@@ -139,3 +132,19 @@ register_toolchains(
# Require users to opt-in to the Pico SDK's toolchains.
dev_dependency = True,
)
+
+python = use_extension("@rules_python//python/extensions:python.bzl", "python")
+python.toolchain(
+ configure_coverage_tool = True,
+ python_version = "3.9",
+)
+
+use_repo(python, "pythons_hub")
+register_toolchains(
+ "@pythons_hub//:all",
+ dev_dependency = True,
+)
+register_toolchains(
+ "@rules_python//python/runtime_env_toolchains:all",
+ dev_dependency = True,
+)
diff --git a/README.md b/README.md
index 6129a007f..69f6c4ef3 100644
--- a/README.md
+++ b/README.md
@@ -51,9 +51,9 @@ You can install the [Raspberry Pi Pico Visual Studio Code extension](https://mar
These instructions are extremely terse, and Linux-based only. For detailed steps,
instructions for other platforms, and just in general, we recommend you see [Raspberry Pi Pico-Series C/C++ SDK](https://rptl.io/pico-c-sdk)
-1. Install CMake (at least version 3.13), and a GCC cross compiler
+1. Install CMake (at least version 3.13), python 3, a native compiler, and a GCC cross compiler
```
- sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
+ sudo apt install cmake python3 build-essential gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
```
1. Set up your project to point to use the Raspberry Pi Pico SDK
@@ -200,4 +200,4 @@ instructions for other platforms, and just in general, we recommend you see [Ras
# RISC-V support on RP2350
-See [Raspberry Pi Pico-series C/C++ SDK](https://rptl.io/pico-c-sdk) for information on setting up a build environment for RISC-V on RP2350.
\ No newline at end of file
+See [Raspberry Pi Pico-series C/C++ SDK](https://rptl.io/pico-c-sdk) for information on setting up a build environment for RISC-V on RP2350.
diff --git a/bazel/README.md b/bazel/README.md
index 6520e7a0f..35b2045cb 100644
--- a/bazel/README.md
+++ b/bazel/README.md
@@ -3,32 +3,10 @@
## Using the Pico SDK in a Bazel project.
### Add pico-sdk as a dependency
-First, in your `MODULE.bazel` file, add a dependency on the Pico SDK:
+First, in your `MODULE.bazel` file, add a dependency on the Pico SDK and
+`rules_cc`:
```python
-bazel_dep(
- name = "pico-sdk",
- version = "2.0.0",
-)
-```
-
-Second, in the same file you'll need to add an explicit dependency on
-`rules_cc`, as it's a special-cased Bazel module:
-```python
-# Note: rules_cc is special-cased repository; a dependency on rules_cc in a
-# module will not ensure that the root Bazel module has that same version of
-# rules_cc. For that reason, this primarily acts as a FYI. You'll still need
-# to explicitly list this dependency in your own project's MODULE.bazel file.
-bazel_dep(name = "rules_cc", version = "0.0.9")
-
-# rules_cc v0.0.10 is not yet cut, so manually pull in the desired version.
-# This does not apply to dependent projects, so it needs to be copied to your
-# project's MODULE.bazel too.
-archive_override(
- module_name = "rules_cc",
- urls = "https://github.com/bazelbuild/rules_cc/archive/1acf5213b6170f1f0133e273cb85ede0e732048f.zip",
- strip_prefix = "rules_cc-1acf5213b6170f1f0133e273cb85ede0e732048f",
- integrity = "sha256-NddP6xi6LzsIHT8bMSVJ2NtoURbN+l3xpjvmIgB6aSg=",
-)
+bazel_dep(name = "pico-sdk", version = "2.1.0")
```
### Register toolchains
@@ -47,15 +25,6 @@ register_toolchains(
)
```
-### Enable required .bazelrc flags
-To use the toolchains provided by the Pico SDK, you'll need to enable a few
-new features. In your project's `.bazelrc`, add the following
-```
-# Required for new toolchain resolution API.
-build --incompatible_enable_cc_toolchain_resolution
-build --@rules_cc//cc/toolchains:experimental_enable_rule_based_toolchains
-```
-
### Ready to build!
You're now ready to start building Pico Projects in Bazel! When building,
don't forget to specify `--platforms` so Bazel knows you're targeting the
@@ -123,11 +92,12 @@ you encounter along the way.
Currently, the following features are not supported:
+* Pico W wireless libraries work, but may not have complete feature parity with
+ the CMake build.
+* Bazel does not yet provide RISC-V support for Pico 2/RP2350.
* The pioasm parser cannot be built from source via Bazel.
* Windows MSVC wildcard build (`bazel build //...`) does not work when targeting
host.
-* Bazel does not yet provide RISC-V support for Pico 2/RP2350.
-* Pico W wireless libraries have link issues.
## Contributing
When making changes to the Bazel build, please run the Bazel validation script
diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel
index 4ab2ccc9b..4e622af5c 100644
--- a/bazel/config/BUILD.bazel
+++ b/bazel/config/BUILD.bazel
@@ -72,6 +72,12 @@ bool_flag(
build_setting_default = True,
)
+# PICO_BAZEL_CONFIG: PICO_DEFAULT_UART_BAUD_RATE, Define the default UART baudrate, type=int, max=921600, default=115200, group=hardware_uart
+int_flag(
+ name = "PICO_DEFAULT_UART_BAUD_RATE",
+ build_setting_default = 115200,
+)
+
# PICO_BAZEL_CONFIG: PICO_STDIO_USB, Option to globally enable stdio USB for all targets by default, type=bool, default=0, group=pico_stdlib
bool_flag(
name = "PICO_STDIO_USB",
@@ -145,13 +151,24 @@ string_flag(
],
)
+# PICO_BAZEL_CONFIG: PICO_ASYNC_CONTEXT_IMPL, The default implementation for pico_async_context to link, type=string, default=threadsafe_background, group=build
+string_flag(
+ name = "PICO_ASYNC_CONTEXT_IMPL",
+ build_setting_default = "threadsafe_background",
+ values = [
+ "poll",
+ "threadsafe_background",
+ "freertos",
+ ],
+)
+
# PICO_BAZEL_CONFIG: PICO_BINARY_INFO_ENABLED, Whether to include binary info in final firmware, type=bool, default=1, group=pico_stdlib
bool_flag(
name = "PICO_BINARY_INFO_ENABLED",
build_setting_default = True,
)
-# PICO_BAZEL_CONFIG: PICO_CMSIS_PATH, Label of a cc_ibrary providing CMSIS core, default="included stub CORE only impl", group=build
+# PICO_BAZEL_CONFIG: PICO_CMSIS_PATH, Label of a cc_ibrary providing CMSIS core, type=string, default="included stub CORE only impl", group=build
label_flag(
name = "PICO_CMSIS_PATH",
build_setting_default = "//src/rp2_common/cmsis:cmsis_core",
@@ -242,6 +259,24 @@ label_flag(
build_setting_default = "//bazel:empty_cc_lib",
)
+# PICO_BAZEL_CONFIG: PICO_BT_ENABLE_BLE, [Bazel only] Whether or not to link in BLE portions of the btstack as part of //src/rp2_common/pico_btstack. Also defines ENABLE_BLE=1, type=bool, default=False, group=wireless
+bool_flag(
+ name = "PICO_BT_ENABLE_BLE",
+ build_setting_default = False,
+)
+
+# PICO_BAZEL_CONFIG: PICO_BT_ENABLE_CLASSIC, [Bazel only] Whether or not to link in classic BT portions of the btstack as part of //src/rp2_common/pico_btstack. Also defines ENABLE_CLASSIC=1, type=bool, default=False, group=wireless
+bool_flag(
+ name = "PICO_BT_ENABLE_CLASSIC",
+ build_setting_default = False,
+)
+
+# PICO_BAZEL_CONFIG: PICO_BT_ENABLE_MESH, [Bazel only] Whether or not to link in mesh BT portions of the btstack as part of //src/rp2_common/pico_btstack. Also defines ENABLE_MESH=1, type=bool, default=False, group=wireless
+bool_flag(
+ name = "PICO_BT_ENABLE_MESH",
+ build_setting_default = False,
+)
+
# PICO_BAZEL_CONFIG: PICO_LWIP_CONFIG, [Bazel only] The cc_library that provides lwipopts.h, default=//bazel:empty_cc_lib, group=wireless
label_flag(
name = "PICO_LWIP_CONFIG",
diff --git a/bazel/constraint/BUILD.bazel b/bazel/constraint/BUILD.bazel
index 05cccb92b..a4fe918b8 100644
--- a/bazel/constraint/BUILD.bazel
+++ b/bazel/constraint/BUILD.bazel
@@ -1,3 +1,5 @@
+load("//bazel/util:label_flag_matches.bzl", "label_flag_matches")
+
package(default_visibility = ["//visibility:public"])
# This constraint represents the dimension that guides the Pico SDK build. This
@@ -48,6 +50,11 @@ config_setting(
flag_values = {"//bazel/config:PICO_BOARD": "pico_w"},
)
+config_setting(
+ name = "is_pico2_w",
+ flag_values = {"//bazel/config:PICO_BOARD": "pico2_w"},
+)
+
config_setting(
name = "pico_toolchain_clang_enabled",
flag_values = {"//bazel/config:PICO_TOOLCHAIN": "clang"},
@@ -173,6 +180,21 @@ config_setting(
flag_values = {"//bazel/config:PICO_DEFAULT_PRINTF_IMPL": "compiler"},
)
+config_setting(
+ name = "pico_async_context_poll_enabled",
+ flag_values = {"//bazel/config:PICO_ASYNC_CONTEXT_IMPL": "poll"},
+)
+
+config_setting(
+ name = "pico_async_context_threadsafe_background_enabled",
+ flag_values = {"//bazel/config:PICO_ASYNC_CONTEXT_IMPL": "threadsafe_background"},
+)
+
+config_setting(
+ name = "pico_async_context_freertos_enabled",
+ flag_values = {"//bazel/config:PICO_ASYNC_CONTEXT_IMPL": "freertos"},
+)
+
config_setting(
name = "pico_use_default_max_page_size_enabled",
flag_values = {"//bazel/config:PICO_USE_DEFAULT_MAX_PAGE_SIZE": "True"},
@@ -199,16 +221,34 @@ config_setting(
)
config_setting(
- name = "pico_btstack_config_unset",
- flag_values = {"//bazel/config:PICO_BTSTACK_CONFIG": "//bazel:empty_cc_lib"},
+ name = "pico_bt_enable_ble_enabled",
+ flag_values = {"//bazel/config:PICO_BT_ENABLE_BLE": "True"},
)
config_setting(
- name = "pico_lwip_config_unset",
- flag_values = {"//bazel/config:PICO_LWIP_CONFIG": "//bazel:empty_cc_lib"},
+ name = "pico_bt_enable_classic_enabled",
+ flag_values = {"//bazel/config:PICO_BT_ENABLE_CLASSIC": "True"},
)
config_setting(
+ name = "pico_bt_enable_mesh_enabled",
+ flag_values = {"//bazel/config:PICO_BT_ENABLE_MESH": "True"},
+)
+
+label_flag_matches(
+ name = "pico_lwip_config_unset",
+ flag = "//bazel/config:PICO_LWIP_CONFIG",
+ value = "//bazel:empty_cc_lib",
+)
+
+label_flag_matches(
+ name = "pico_btstack_config_unset",
+ flag = "//bazel/config:PICO_BTSTACK_CONFIG",
+ value = "//bazel:empty_cc_lib",
+)
+
+label_flag_matches(
name = "pico_freertos_unset",
- flag_values = {"//bazel/config:PICO_FREERTOS_LIB": "//bazel:empty_cc_lib"},
+ flag = "//bazel/config:PICO_FREERTOS_LIB",
+ value = "//bazel:empty_cc_lib",
)
diff --git a/bazel/defs.bzl b/bazel/defs.bzl
index 0e9df1a26..888f59cea 100644
--- a/bazel/defs.bzl
+++ b/bazel/defs.bzl
@@ -88,6 +88,7 @@ def compatible_with_pico_w():
return select({
"@pico-sdk//bazel/constraint:cyw43_wireless": [],
"@pico-sdk//bazel/constraint:is_pico_w": [],
+ "@pico-sdk//bazel/constraint:is_pico2_w": [],
"//conditions:default": ["@platforms//:incompatible"],
})
diff --git a/bazel/pico_btstack_make_gatt_header.bzl b/bazel/pico_btstack_make_gatt_header.bzl
new file mode 100644
index 000000000..e9468fbf0
--- /dev/null
+++ b/bazel/pico_btstack_make_gatt_header.bzl
@@ -0,0 +1,59 @@
+load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain", "use_cc_toolchain")
+
+def _pico_btstack_make_gatt_header_impl(ctx):
+ cc_toolchain = find_cpp_toolchain(ctx)
+ feature_configuration = cc_common.configure_features(
+ ctx = ctx,
+ cc_toolchain = cc_toolchain,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features,
+ )
+
+ out = ctx.actions.declare_file(
+ "{}_gatt_generated/{}.h".format(ctx.label.name, ctx.file.src.basename.removesuffix(".gatt")),
+ )
+
+ ctx.actions.run(
+ executable = ctx.executable._make_gat_header_tool,
+ arguments = [
+ ctx.file.src.path,
+ out.path,
+ "-I",
+ ctx.file._btstack_hdr.dirname,
+ ] + [
+
+ ],
+ inputs = [
+ ctx.file.src,
+ ctx.file._btstack_hdr,
+ ],
+ outputs = [out],
+ )
+
+ cc_ctx = cc_common.create_compilation_context(
+ headers = depset(direct = [out]),
+ includes = depset(direct = [out.dirname]),
+ )
+
+ return [
+ DefaultInfo(files = depset(direct = [out])),
+ CcInfo(compilation_context = cc_ctx)
+ ]
+
+pico_btstack_make_gatt_header = rule(
+ implementation = _pico_btstack_make_gatt_header_impl,
+ attrs = {
+ "src": attr.label(mandatory = True, allow_single_file = True),
+ "_btstack_hdr": attr.label(
+ default = "@btstack//:src/bluetooth_gatt.h",
+ allow_single_file = True,
+ ),
+ "_make_gat_header_tool": attr.label(
+ default = "@btstack//:compile_gatt",
+ cfg = "exec",
+ executable = True,
+ ),
+ },
+ fragments = ["cpp"],
+ toolchains = use_cc_toolchain(),
+)
diff --git a/bazel/toolchain/BUILD.bazel b/bazel/toolchain/BUILD.bazel
index 9e0f7719f..bba5baafd 100644
--- a/bazel/toolchain/BUILD.bazel
+++ b/bazel/toolchain/BUILD.bazel
@@ -51,36 +51,39 @@ cc_args(
],
)
+# :no_canonical_system_headers and :no_canonical_prefixes both prevent built-in
+# compiler include directories from resolving to absolute paths. Prefer to use
+# :bazel_no_absolute_paths, since it correctly guides based on the current
+# compiler type.
cc_args(
- name = "no-canonical-system-headers",
+ name = "no_canonical_system_headers",
actions = ["@rules_cc//cc/toolchains/actions:compile_actions"],
args = ["-fno-canonical-system-headers"],
)
cc_args(
- name = "no-canonical-prefixes",
+ name = "no_canonical_prefixes",
actions = ["@rules_cc//cc/toolchains/actions:compile_actions"],
args = ["-no-canonical-prefixes"],
)
-cc_args(
- name = "nostdlibxx",
- actions = ["@rules_cc//cc/toolchains/actions:link_actions"],
- args = ["-nostdlib++"],
-)
-
-cc_args(
- name = "nostartfiles",
- actions = ["@rules_cc//cc/toolchains/actions:link_actions"],
- args = ["-nostartfiles"],
-)
-
cc_args_list(
name = "bazel_no_absolute_paths",
args = select({
"//bazel/constraint:pico_toolchain_clang_enabled": [],
- "//conditions:default": [":no-canonical-system-headers"],
- }) + [":no-canonical-prefixes"],
+ "//conditions:default": [":no_canonical_system_headers"],
+ }) + [":no_canonical_prefixes"],
+)
+
+cc_args(
+ name = "llvm-libc_args",
+ actions = ["@rules_cc//cc/toolchains/actions:link_actions"],
+ args = [
+ "-nostdlib++",
+ "-nostartfiles",
+ "-Wl,-lc++",
+ ],
+ visibility = ["//visibility:private"],
)
cc_args(
@@ -101,7 +104,6 @@ configurable_toolchain_feature(
"-ffunction-sections",
"-fdata-sections",
],
- disable_if = "//bazel/constraint:pico_no_gc_sections_enabled",
linkopts = ["-Wl,--gc-sections"],
)
@@ -111,24 +113,20 @@ configurable_toolchain_feature(
"-fno-exceptions",
"-fno-unwind-tables",
],
- disable_if = "//bazel/constraint:pico_cxx_enable_exceptions_enabled",
)
configurable_toolchain_feature(
name = "cxx_no_rtti",
cxxopts = ["-fno-rtti"],
- disable_if = "//bazel/constraint:pico_cxx_enable_rtti_enabled",
)
configurable_toolchain_feature(
name = "cxx_no_cxa_atexit",
cxxopts = ["-fno-use-cxa-atexit"],
- disable_if = "//bazel/constraint:pico_cxx_enable_cxa_atexit_enabled",
)
configurable_toolchain_feature(
name = "override_max_page_size",
- disable_if = "//bazel/constraint:pico_use_default_max_page_size_enabled",
linkopts = ["-Wl,-z,max-page-size=4096"],
)
@@ -141,38 +139,12 @@ cc_args_list(
cc_feature(
name = "override_debug",
args = [":all_opt_debug_args"],
- enabled = True,
overrides = "@rules_cc//cc/toolchains/features:dbg",
)
-# TODO: https://github.com/bazelbuild/rules_cc/issues/224 - This is required for
-# now, but hopefully will eventually go away.
-cc_feature(
- name = "legacy_features",
- args = [],
- enabled = True,
- feature_name = "force_legacy_features",
- implies = [
- "@rules_cc//cc/toolchains/features/legacy:archiver_flags",
- "@rules_cc//cc/toolchains/features/legacy:build_interface_libraries",
- "@rules_cc//cc/toolchains/features/legacy:dynamic_library_linker_tool",
- "@rules_cc//cc/toolchains/features/legacy:strip_debug_symbols",
- "@rules_cc//cc/toolchains/features/legacy:linkstamps",
- "@rules_cc//cc/toolchains/features/legacy:output_execpath_flags",
- "@rules_cc//cc/toolchains/features/legacy:runtime_library_search_directories",
- "@rules_cc//cc/toolchains/features/legacy:library_search_directories",
- "@rules_cc//cc/toolchains/features/legacy:libraries_to_link",
- "@rules_cc//cc/toolchains/features/legacy:force_pic_flags",
- "@rules_cc//cc/toolchains/features/legacy:user_link_flags",
- "@rules_cc//cc/toolchains/features/legacy:legacy_link_flags",
- "@rules_cc//cc/toolchains/features/legacy:linker_param_file",
- "@rules_cc//cc/toolchains/features/legacy:fission_support",
- "@rules_cc//cc/toolchains/features/legacy:sysroot",
- ],
-)
-
HOSTS = (
("linux", "x86_64"),
+ ("linux", "aarch64"),
("win", "x86_64"),
("mac", "x86_64"),
("mac", "aarch64"),
@@ -191,14 +163,7 @@ _HOST_CPU_CONSTRAINTS = {
[cc_toolchain(
name = "arm_gcc_{}-{}_toolchain_cortex-m".format(host_os, host_cpu),
- action_type_configs = [
- "@arm_gcc_{}-{}//:arm-none-eabi-ar".format(host_os, host_cpu),
- "@arm_gcc_{}-{}//:arm-none-eabi-gcc".format(host_os, host_cpu),
- "@arm_gcc_{}-{}//:arm-none-eabi-g++".format(host_os, host_cpu),
- "@arm_gcc_{}-{}//:arm-none-eabi-ld".format(host_os, host_cpu),
- "@arm_gcc_{}-{}//:arm-none-eabi-objcopy".format(host_os, host_cpu),
- "@arm_gcc_{}-{}//:arm-none-eabi-strip".format(host_os, host_cpu),
- ],
+ tool_map = "@arm_gcc_{}-{}//:all_tools".format(host_os, host_cpu),
args = select({
"//bazel/constraint:rp2040": [":cortex-m0"],
"//bazel/constraint:rp2350": [":cortex-m33"],
@@ -206,24 +171,13 @@ _HOST_CPU_CONSTRAINTS = {
}) + [
":bazel_no_absolute_paths",
],
- compiler = "gcc", # Useful for distinguishing gcc vs clang.
- cxx_builtin_include_directories = [
- "%sysroot%/arm-none-eabi/include/newlib-nano",
- "%sysroot%/arm-none-eabi/include/c++/13.2.1",
- "%sysroot%/arm-none-eabi/include/c++/13.2.1/arm-none-eabi",
- "%sysroot%/arm-none-eabi/include/c++/13.2.1/backward",
- "%sysroot%/lib/gcc/arm-none-eabi/13.2.1/include",
- "%sysroot%/lib/gcc/arm-none-eabi/13.2.1/include-fixed",
- "%sysroot%/arm-none-eabi/include",
- ],
exec_compatible_with = [
_HOST_CPU_CONSTRAINTS[host_cpu],
_HOST_OS_CONSTRAINTS[host_os],
],
- sysroot = "external/arm_gcc_{}-{}".format(host_os, host_cpu),
tags = ["manual"], # Don't try to build this in wildcard builds.
- toolchain_features = [
- "@pico-sdk//bazel/toolchain:legacy_features",
+ known_features = [
+ "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features",
"@pico-sdk//bazel/toolchain:override_debug",
"@pico-sdk//bazel/toolchain:gc_sections",
"@pico-sdk//bazel/toolchain:cxx_no_exceptions",
@@ -231,18 +185,30 @@ _HOST_CPU_CONSTRAINTS = {
"@pico-sdk//bazel/toolchain:cxx_no_cxa_atexit",
"@pico-sdk//bazel/toolchain:override_max_page_size",
],
+ enabled_features = [
+ "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features",
+ "@pico-sdk//bazel/toolchain:override_debug",
+ ] + select({
+ "//bazel/constraint:pico_no_gc_sections_enabled": [],
+ "//conditions:default": [":gc_sections"],
+ }) + select({
+ "//bazel/constraint:pico_cxx_enable_exceptions_enabled": [],
+ "//conditions:default": [":cxx_no_exceptions"],
+ }) + select({
+ "//bazel/constraint:pico_cxx_enable_rtti_enabled": [],
+ "//conditions:default": [":cxx_no_rtti"],
+ }) + select({
+ "//bazel/constraint:pico_cxx_enable_cxa_atexit_enabled": [],
+ "//conditions:default": [":cxx_no_cxa_atexit"],
+ }) + select({
+ "//bazel/constraint:pico_use_default_max_page_size_enabled": [],
+ "//conditions:default": [":override_max_page_size"],
+ }),
) for host_os, host_cpu in HOSTS]
[cc_toolchain(
name = "clang_{}-{}_toolchain_cortex-m".format(host_os, host_cpu),
- action_type_configs = [
- "@clang_{}-{}//:llvm-ar".format(host_os, host_cpu),
- "@clang_{}-{}//:clang".format(host_os, host_cpu),
- "@clang_{}-{}//:clang++".format(host_os, host_cpu),
- "@clang_{}-{}//:lld".format(host_os, host_cpu),
- "@clang_{}-{}//:llvm-objcopy".format(host_os, host_cpu),
- "@clang_{}-{}//:llvm-strip".format(host_os, host_cpu),
- ],
+ tool_map = "@clang_{}-{}//:all_tools".format(host_os, host_cpu),
args = select({
"//bazel/constraint:rp2040": [
":armv6m-none-eabi",
@@ -255,17 +221,15 @@ _HOST_CPU_CONSTRAINTS = {
"//conditions:default": [],
}) + [
":bazel_no_absolute_paths",
- ":nostdlibxx",
- ":nostartfiles",
+ ":llvm-libc_args",
],
- compiler = "clang", # Useful for distinguishing gcc vs clang.
exec_compatible_with = [
_HOST_CPU_CONSTRAINTS[host_cpu],
_HOST_OS_CONSTRAINTS[host_os],
],
tags = ["manual"], # Don't try to build this in wildcard builds.
- toolchain_features = [
- "@pico-sdk//bazel/toolchain:legacy_features",
+ known_features = [
+ "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features",
"@pico-sdk//bazel/toolchain:override_debug",
"@pico-sdk//bazel/toolchain:gc_sections",
"@pico-sdk//bazel/toolchain:cxx_no_exceptions",
@@ -273,6 +237,25 @@ _HOST_CPU_CONSTRAINTS = {
"@pico-sdk//bazel/toolchain:cxx_no_cxa_atexit",
"@pico-sdk//bazel/toolchain:override_max_page_size",
],
+ enabled_features = [
+ "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features",
+ "@pico-sdk//bazel/toolchain:override_debug",
+ ] + select({
+ "//bazel/constraint:pico_no_gc_sections_enabled": [],
+ "//conditions:default": [":gc_sections"],
+ }) + select({
+ "//bazel/constraint:pico_cxx_enable_exceptions_enabled": [],
+ "//conditions:default": [":cxx_no_exceptions"],
+ }) + select({
+ "//bazel/constraint:pico_cxx_enable_rtti_enabled": [],
+ "//conditions:default": [":cxx_no_rtti"],
+ }) + select({
+ "//bazel/constraint:pico_cxx_enable_cxa_atexit_enabled": [],
+ "//conditions:default": [":cxx_no_cxa_atexit"],
+ }) + select({
+ "//bazel/constraint:pico_use_default_max_page_size_enabled": [],
+ "//conditions:default": [":override_max_page_size"],
+ }),
) for host_os, host_cpu in HOSTS]
[toolchain(
diff --git a/bazel/toolchain/clang.BUILD b/bazel/toolchain/clang.BUILD
index 426fc3339..ef9344f5d 100644
--- a/bazel/toolchain/clang.BUILD
+++ b/bazel/toolchain/clang.BUILD
@@ -1,170 +1,152 @@
-load("@rules_cc//cc/toolchains:action_type_config.bzl", "cc_action_type_config")
+load("@bazel_skylib//rules/directory:directory.bzl", "directory")
+load("@bazel_skylib//rules/directory:subdirectory.bzl", "subdirectory")
load("@rules_cc//cc/toolchains:tool.bzl", "cc_tool")
+load("@rules_cc//cc/toolchains:tool_map.bzl", "cc_tool_map")
+load("@rules_cc//cc/toolchains:args.bzl", "cc_args")
+load("@rules_cc//cc/toolchains:args_list.bzl", "cc_args_list")
package(default_visibility = ["//visibility:public"])
-cc_tool(
- name = "llvm-ar_tool",
- src = select({
- "@platforms//os:windows": "//:bin/llvm-ar.exe",
- "//conditions:default": "//:bin/llvm-ar",
- }),
- data = select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
- }),
+licenses(["notice"])
+
+# Directory-based rules in this toolchain only referece things in
+# lib/ or include/ subdirectories.
+directory(
+ name = "toolchain_root",
+ srcs = glob([
+ "lib/**",
+ "include/**",
+ ]),
)
-cc_action_type_config(
- name = "llvm-ar",
- action_types = ["@rules_cc//cc/toolchains/actions:ar_actions"],
- tools = [":llvm-ar_tool"],
+cc_tool_map(
+ name = "all_tools",
+ tools = {
+ "@rules_cc//cc/toolchains/actions:assembly_actions": ":asm",
+ "@rules_cc//cc/toolchains/actions:c_compile": ":clang",
+ "@rules_cc//cc/toolchains/actions:cpp_compile_actions": ":clang++",
+ "@rules_cc//cc/toolchains/actions:link_actions": ":lld",
+ "@rules_cc//cc/toolchains/actions:objcopy_embed_data": ":llvm-objcopy",
+ "@rules_cc//cc/toolchains/actions:strip": ":llvm-strip",
+ "@rules_cc//cc/toolchains/actions:ar_actions": ":llvm-ar",
+ },
+)
+
+# TODO: https://github.com/bazelbuild/rules_cc/issues/235 - Workaround until
+# Bazel has a more robust way to implement `cc_tool_map`.
+alias(
+ name = "asm",
+ actual = ":clang",
)
cc_tool(
- name = "clang_tool",
+ name = "clang",
src = select({
"@platforms//os:windows": "//:bin/clang.exe",
"//conditions:default": "//:bin/clang",
}),
data = glob([
- "include/armv*-unknown-none-eabi/**",
+ "bin/llvm",
"lib/clang/*/include/**",
- ]) + select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
- }),
-)
-
-cc_action_type_config(
- name = "clang",
- action_types = [
- "@rules_cc//cc/toolchains/actions:assembly_actions",
- "@rules_cc//cc/toolchains/actions:c_compile",
- ],
- tools = [":clang_tool"],
+ "include/armv*-unknown-none-eabi/**",
+ ]),
)
cc_tool(
- name = "clang++_tool",
+ name = "clang++",
src = select({
"@platforms//os:windows": "//:bin/clang++.exe",
"//conditions:default": "//:bin/clang++",
}),
data = glob([
- "include/armv*-unknown-none-eabi/**",
- "include/c++/**",
+ "bin/llvm",
"lib/clang/*/include/**",
- ]) + select({
- # Windows doesn't have llvm.exe.
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
- }),
-)
-
-cc_action_type_config(
- name = "clang++",
- action_types = ["@rules_cc//cc/toolchains/actions:cpp_compile_actions"],
- tools = [":clang++_tool"],
+ "include/armv*-unknown-none-eabi/**",
+ "include/c++/v1/**",
+ ]),
)
-# This tool is actually just clang++ under the hood, but this specifies a
-# different set of data files to pull into the sandbox at runtime.
cc_tool(
- name = "lld_tool",
+ name = "lld",
src = select({
"@platforms//os:windows": "//:bin/clang++.exe",
"//conditions:default": "//:bin/clang++",
}),
data = glob([
+ "bin/llvm",
+ "bin/lld*",
+ "bin/ld*",
+ "lib/**/*.a",
+ "lib/**/*.so*",
+ "lib/**/*.o",
"lib/armv*-unknown-none-eabi/**",
"lib/clang/*/lib/armv*-unknown-none-eabi/**",
- ]) + select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
- }),
-)
-
-cc_action_type_config(
- name = "lld",
- action_types = ["@rules_cc//cc/toolchains/actions:link_actions"],
- tools = [":lld_tool"],
+ ]),
)
cc_tool(
- name = "llvm-objcopy_tool",
+ name = "llvm-ar",
src = select({
- "@platforms//os:windows": "//:bin/llvm-objcopy.exe",
- "//conditions:default": "//:bin/llvm-objcopy",
- }),
- data = select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
+ "@platforms//os:windows": "//:bin/llvm-ar.exe",
+ "//conditions:default": "//:bin/llvm-ar",
}),
-)
-
-cc_action_type_config(
- name = "llvm-objcopy",
- action_types = ["@rules_cc//cc/toolchains/actions:objcopy_embed_data"],
- tools = [":llvm-objcopy_tool"],
+ data = glob(["bin/llvm"]),
)
cc_tool(
- name = "llvm-strip_tool",
+ name = "llvm-libtool-darwin",
src = select({
- "@platforms//os:windows": "//:bin/llvm-strip.exe",
- "//conditions:default": "//:bin/llvm-strip",
- }),
- data = select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
+ "@platforms//os:windows": "//:bin/llvm-libtool-darwin.exe",
+ "//conditions:default": "//:bin/llvm-libtool-darwin",
}),
+ data = glob(["bin/llvm"]),
)
-cc_action_type_config(
- name = "llvm-strip",
- action_types = ["@rules_cc//cc/toolchains/actions:strip"],
- tools = [":llvm-strip_tool"],
+cc_tool(
+ name = "llvm-objcopy",
+ src = select({
+ "@platforms//os:windows": "//:bin/llvm-objcopy.exe",
+ "//conditions:default": "//:bin/llvm-objcopy",
+ }),
+ data = glob(["bin/llvm"]),
)
cc_tool(
- name = "llvm-objdump_tool",
+ name = "llvm-objdump",
src = select({
"@platforms//os:windows": "//:bin/llvm-objdump.exe",
"//conditions:default": "//:bin/llvm-objdump",
}),
- data = select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
- }),
+ data = glob(["bin/llvm"]),
)
-# There is not yet a well-known action type for llvm-objdump.
-
cc_tool(
- name = "llvm-profdata_tool",
+ name = "llvm-cov",
src = select({
- "@platforms//os:windows": "//:bin/llvm-profdata.exe",
- "//conditions:default": "//:bin/llvm-profdata",
- }),
- data = select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
+ "@platforms//os:windows": "//:bin/llvm-cov.exe",
+ "//conditions:default": "//:bin/llvm-cov",
}),
+ data = glob(["bin/llvm"]),
)
-# There is not yet a well-known action type for llvm-profdata.
-
cc_tool(
- name = "llvm-cov_tool",
+ name = "llvm-strip",
src = select({
- "@platforms//os:windows": "//:bin/llvm-cov.exe",
- "//conditions:default": "//:bin/llvm-cov",
- }),
- data = select({
- "@platforms//os:windows": [],
- "//conditions:default": ["//:bin/llvm"],
+ "@platforms//os:windows": "//:bin/llvm-strip.exe",
+ "//conditions:default": "//:bin/llvm-strip",
}),
+ data = glob(["bin/llvm"]),
)
-# There is not yet a well-known action type for llvm-cov.
+cc_tool(
+ name = "clang-tidy",
+ src = select({
+ "@platforms//os:windows": "//:bin/clang-tidy.exe",
+ "//conditions:default": "//:bin/clang-tidy",
+ }),
+ data = glob([
+ "bin/llvm",
+ "include/**",
+ "lib/clang/**/include/**",
+ ]),
+)
diff --git a/bazel/toolchain/configurable_feature.bzl b/bazel/toolchain/configurable_feature.bzl
index 019c3df1e..98f9d8a2a 100644
--- a/bazel/toolchain/configurable_feature.bzl
+++ b/bazel/toolchain/configurable_feature.bzl
@@ -2,15 +2,7 @@ load("@rules_cc//cc/toolchains:args.bzl", "cc_args")
load("@rules_cc//cc/toolchains:args_list.bzl", "cc_args_list")
load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature")
-def configurable_toolchain_feature(name, copts = [], cxxopts = [], linkopts = [], enable_if = None, disable_if = None):
- if enable_if != None and disable_if != None:
- fail("Cannot specify both enable_if and disable_if")
- if enable_if == None and disable_if == None:
- fail("Must specify at least one of enable_if and disable_if")
- if enable_if == None:
- enable_if = "//conditions:default"
- if disable_if == None:
- disable_if = "//conditions:default"
+def configurable_toolchain_feature(name, copts = [], cxxopts = [], linkopts = []):
all_args = []
@@ -47,8 +39,4 @@ def configurable_toolchain_feature(name, copts = [], cxxopts = [], linkopts = []
name = name,
feature_name = name,
args = [":{}_args".format(name)],
- enabled = select({
- disable_if: False,
- enable_if: True,
- }),
)
diff --git a/bazel/toolchain/gcc_arm_none_eabi.BUILD b/bazel/toolchain/gcc_arm_none_eabi.BUILD
index 56bb0972f..d5b8a0468 100644
--- a/bazel/toolchain/gcc_arm_none_eabi.BUILD
+++ b/bazel/toolchain/gcc_arm_none_eabi.BUILD
@@ -1,24 +1,43 @@
-load("@rules_cc//cc/toolchains:action_type_config.bzl", "cc_action_type_config")
+load("@bazel_skylib//rules/directory:directory.bzl", "directory")
+load("@bazel_skylib//rules/directory:subdirectory.bzl", "subdirectory")
load("@rules_cc//cc/toolchains:tool.bzl", "cc_tool")
+load("@rules_cc//cc/toolchains:tool_map.bzl", "cc_tool_map")
+load("@rules_cc//cc/toolchains:args.bzl", "cc_args")
+load("@rules_cc//cc/toolchains:args_list.bzl", "cc_args_list")
+
package(default_visibility = ["//visibility:public"])
+cc_tool_map(
+ name = "all_tools",
+ tools = {
+ "@rules_cc//cc/toolchains/actions:assembly_actions": ":asm",
+ "@rules_cc//cc/toolchains/actions:c_compile": ":arm-none-eabi-gcc",
+ "@rules_cc//cc/toolchains/actions:cpp_compile_actions": ":arm-none-eabi-g++",
+ "@rules_cc//cc/toolchains/actions:link_actions": ":arm-none-eabi-ld",
+ "@rules_cc//cc/toolchains/actions:objcopy_embed_data": ":arm-none-eabi-objcopy",
+ "@rules_cc//cc/toolchains/actions:strip": ":arm-none-eabi-strip",
+ "@rules_cc//cc/toolchains/actions:ar_actions": ":arm-none-eabi-ar",
+ },
+)
+
+# TODO: https://github.com/bazelbuild/rules_cc/issues/235 - Workaround until
+# Bazel has a more robust way to implement `cc_tool_map`.
+alias(
+ name = "asm",
+ actual = ":arm-none-eabi-gcc",
+)
+
cc_tool(
- name = "arm-none-eabi-ar_tool",
+ name = "arm-none-eabi-ar",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-ar.exe",
"//conditions:default": "//:bin/arm-none-eabi-ar",
}),
)
-cc_action_type_config(
- name = "arm-none-eabi-ar",
- action_types = ["@rules_cc//cc/toolchains/actions:ar_actions"],
- tools = [":arm-none-eabi-ar_tool"],
-)
-
cc_tool(
- name = "arm-none-eabi-g++_tool",
+ name = "arm-none-eabi-g++",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-g++.exe",
"//conditions:default": "//:bin/arm-none-eabi-g++",
@@ -33,14 +52,8 @@ cc_tool(
]),
)
-cc_action_type_config(
- name = "arm-none-eabi-g++",
- action_types = ["@rules_cc//cc/toolchains/actions:cpp_compile_actions"],
- tools = [":arm-none-eabi-g++_tool"],
-)
-
cc_tool(
- name = "arm-none-eabi-gcc_tool",
+ name = "arm-none-eabi-gcc",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-gcc.exe",
"//conditions:default": "//:bin/arm-none-eabi-gcc",
@@ -62,19 +75,10 @@ cc_tool(
}),
)
-cc_action_type_config(
- name = "arm-none-eabi-gcc",
- action_types = [
- "@rules_cc//cc/toolchains/actions:assembly_actions",
- "@rules_cc//cc/toolchains/actions:c_compile",
- ],
- tools = [":arm-none-eabi-gcc_tool"],
-)
-
# This tool is actually just g++ under the hood, but this specifies a
# different set of data files to pull into the sandbox at runtime.
cc_tool(
- name = "arm-none-eabi-ld_tool",
+ name = "arm-none-eabi-ld",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-g++.exe",
"//conditions:default": "//:bin/arm-none-eabi-g++",
@@ -90,42 +94,24 @@ cc_tool(
]),
)
-cc_action_type_config(
- name = "arm-none-eabi-ld",
- action_types = ["@rules_cc//cc/toolchains/actions:link_actions"],
- tools = [":arm-none-eabi-ld_tool"],
-)
-
cc_tool(
- name = "arm-none-eabi-objcopy_tool",
+ name = "arm-none-eabi-objcopy",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-objcopy.exe",
"//conditions:default": "//:bin/arm-none-eabi-objcopy",
}),
)
-cc_action_type_config(
- name = "arm-none-eabi-objcopy",
- action_types = ["@rules_cc//cc/toolchains/actions:objcopy_embed_data"],
- tools = [":arm-none-eabi-objcopy_tool"],
-)
-
cc_tool(
- name = "arm-none-eabi-strip_tool",
+ name = "arm-none-eabi-strip",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-strip.exe",
"//conditions:default": "//:bin/arm-none-eabi-strip",
}),
)
-cc_action_type_config(
- name = "arm-none-eabi-strip",
- action_types = ["@rules_cc//cc/toolchains/actions:strip"],
- tools = [":arm-none-eabi-strip_tool"],
-)
-
cc_tool(
- name = "arm-none-eabi-objdump_tool",
+ name = "arm-none-eabi-objdump",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-objdump.exe",
"//conditions:default": "//:bin/arm-none-eabi-objdump",
@@ -135,7 +121,7 @@ cc_tool(
# There is not yet a well-known action type for objdump.
cc_tool(
- name = "arm-none-eabi-gcov_tool",
+ name = "arm-none-eabi-gcov",
src = select({
"@platforms//os:windows": "//:bin/arm-none-eabi-gcov.exe",
"//conditions:default": "//:bin/arm-none-eabi-gcov",
diff --git a/bazel/util/label_flag_matches.bzl b/bazel/util/label_flag_matches.bzl
new file mode 100644
index 000000000..a83758432
--- /dev/null
+++ b/bazel/util/label_flag_matches.bzl
@@ -0,0 +1,37 @@
+"""A wrapper that enables a `config_setting` matcher for label_flag flags."""
+
+load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
+load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
+
+def _match_label_flag_impl(ctx):
+ matches = str(ctx.attr.expected_value.label) == str(ctx.attr.flag.label)
+ return [
+ config_common.FeatureFlagInfo(value = str(matches)),
+ BuildSettingInfo(value = matches),
+ ]
+
+_match_label_flag = rule(
+ implementation = _match_label_flag_impl,
+ attrs = {
+ "expected_value": attr.label(
+ mandatory = True,
+ doc = "The expected flag value",
+ ),
+ "flag": attr.label(
+ mandatory = True,
+ doc = "The flag to extract a value from",
+ ),
+ },
+)
+
+def label_flag_matches(*, name, flag, value):
+ _match_label_flag(
+ name = name + "._impl",
+ expected_value = native.package_relative_label(value),
+ flag = flag,
+ )
+
+ native.config_setting(
+ name = name,
+ flag_values = {":{}".format(name + "._impl"): "True"},
+ )
diff --git a/bazel/util/transition.bzl b/bazel/util/transition.bzl
index 5346c2583..67f0d616e 100644
--- a/bazel/util/transition.bzl
+++ b/bazel/util/transition.bzl
@@ -1,3 +1,9 @@
+def _normalize_flag_value(val):
+ """Converts flag values to transition-safe primitives."""
+ if type(val) == "label":
+ return str(val)
+ return val
+
def declare_transtion(attrs, flag_overrides = None, append_to_flags = None, executable = True):
"""A helper that drastically simplifies declaration of a transition.
@@ -31,7 +37,7 @@ def declare_transtion(attrs, flag_overrides = None, append_to_flags = None, exec
final_overrides = {}
if flag_overrides != None:
final_overrides = {
- key: str(getattr(attrs, value))
+ key: _normalize_flag_value(getattr(attrs, value))
for key, value in flag_overrides.items()
}
if append_to_flags != None:
@@ -87,11 +93,18 @@ rp2040_bootloader_binary = declare_transtion(
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
+ "_link_extra_libs": attr.label(default = "//bazel:empty_cc_lib"),
},
flag_overrides = {
# We don't want --custom_malloc to ever apply to the bootloader, so
# always explicitly override it here.
"//command_line_option:custom_malloc": "_malloc",
+
+ # Platforms will commonly depend on bootloader components in every
+ # binary via `link_extra_libs`, so we must drop these deps when
+ # building the bootloader binaries themselves in order to avoid a
+ # circular dependency.
+ "@bazel_tools//tools/cpp:link_extra_libs": "_link_extra_libs",
},
)
@@ -101,6 +114,8 @@ kitchen_sink_test_binary = declare_transtion(
attrs = {
"bt_stack_config": attr.label(mandatory = True),
"lwip_config": attr.label(mandatory = True),
+ "enable_ble": attr.bool(default = False),
+ "enable_bt_classic": attr.bool(default = False),
# This could be shared, but we don't in order to make it clearer that
# a transition is in use.
"_allowlist_function_transition": attr.label(
@@ -110,6 +125,8 @@ kitchen_sink_test_binary = declare_transtion(
flag_overrides = {
"@pico-sdk//bazel/config:PICO_BTSTACK_CONFIG": "bt_stack_config",
"@pico-sdk//bazel/config:PICO_LWIP_CONFIG": "lwip_config",
+ "@pico-sdk//bazel/config:PICO_BT_ENABLE_BLE": "enable_ble",
+ "@pico-sdk//bazel/config:PICO_BT_ENABLE_CLASSIC": "enable_bt_classic",
},
)
diff --git a/cmake/Platform/PICO.cmake b/cmake/Platform/PICO.cmake
index 06388b503..c21714b54 100644
--- a/cmake/Platform/PICO.cmake
+++ b/cmake/Platform/PICO.cmake
@@ -1,4 +1,11 @@
# this is included because toolchain file sets SYSTEM_NAME=PICO
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
-set(CMAKE_EXECUTABLE_SUFFIX .elf)
\ No newline at end of file
+set(CMAKE_EXECUTABLE_SUFFIX .elf)
+
+# include paths to find installed tools
+if(CMAKE_HOST_WIN32)
+ include(Platform/WindowsPaths)
+else()
+ include(Platform/UnixPaths)
+endif()
diff --git a/cmake/generic_board.cmake b/cmake/generic_board.cmake
index 5238f205b..c7fdfe5a0 100644
--- a/cmake/generic_board.cmake
+++ b/cmake/generic_board.cmake
@@ -1,4 +1,5 @@
# For boards without their own cmake file, we look for a header file
+cmake_minimum_required(VERSION 3.15)
# PICO_CMAKE_CONFIG: PICO_BOARD_HEADER_DIRS, List of directories to look for .h in. This may be specified the user environment, type=list, group=build
if (DEFINED ENV{PICO_BOARD_HEADER_DIRS})
@@ -25,6 +26,8 @@ if (EXISTS ${PICO_BOARD_HEADER_FILE})
if (LINE MATCHES "^[ \t\]*//[ \t\]*pico_cmake_set_default[ \t\]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t\]*=[ \t\]*(.*)")
if (NOT DEFINED "${CMAKE_MATCH_1}")
set("${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}")
+ else()
+ list(APPEND PICO_BOARD_CMAKE_OVERRIDES ${CMAKE_MATCH_1})
endif()
endif()
endwhile()
diff --git a/cmake/pico_pre_load_platform.cmake b/cmake/pico_pre_load_platform.cmake
index 7a2c2ab2d..df9aebdd7 100644
--- a/cmake/pico_pre_load_platform.cmake
+++ b/cmake/pico_pre_load_platform.cmake
@@ -13,7 +13,7 @@ if (DEFINED ENV{PICO_PLATFORM} AND NOT PICO_PLATFORM)
endif()
set(PICO_SAVED_PLATFORM "${PICO_PLATFORM}")
-# If PICO_PLATFORM is specified byt not PICO_BOARD, we'll make a stab at defaulting
+# If PICO_PLATFORM is specified but not PICO_BOARD, we'll make a stab at defaulting
if (NOT PICO_DEFAULT_BOARD_rp2040)
set(PICO_DEFAULT_BOARD_rp2040 "pico")
endif()
@@ -84,7 +84,7 @@ if (NOT COMMAND pico_expand_pico_platform)
function(pico_expand_pico_platform FUNC DO_MESSAGE)
if (${FUNC} STREQUAL "rp2350")
if (DO_MESSAGE)
- message("Auto-converting non-specific PICO_PLATFORM='rp2350' to 'rp2350-arm-s'")
+ message("Auto-converting non-specific PICO_PLATFORM='rp2350' to '${PICO_DEFAULT_RP2350_PLATFORM}'")
endif()
set(${FUNC} "${PICO_DEFAULT_RP2350_PLATFORM}" PARENT_SCOPE)
endif()
diff --git a/cmake/preload/toolchains/util/pico_arm_gcc_common.cmake b/cmake/preload/toolchains/util/pico_arm_gcc_common.cmake
index 053e1b165..3178136e1 100644
--- a/cmake/preload/toolchains/util/pico_arm_gcc_common.cmake
+++ b/cmake/preload/toolchains/util/pico_arm_gcc_common.cmake
@@ -3,7 +3,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/find_compiler.cmake)
# include our Platform/PICO.cmake
set(CMAKE_SYSTEM_NAME PICO)
-# PICO_CMAKE_CONFIG: PICO_GCC_TRIPLE, List of GCC_TRIPLES -- usually only one -- to try when searching for a compiler. This may be specified the user environment, type=int, default=PICO_DEFAULT_GCC_TRIPLE which is set based on PICO_COMPILER, group=pico_base, doxref=cmake-toolchain-config
+# PICO_CMAKE_CONFIG: PICO_GCC_TRIPLE, List of GCC_TRIPLES -- usually only one -- to try when searching for a compiler. This may be specified the user environment, type=int, default=PICO_DEFAULT_GCC_TRIPLE which is set based on PICO_COMPILER, group=pico_base, docref=cmake-toolchain-config
if (NOT PICO_GCC_TRIPLE)
if (DEFINED ENV{_SAVED_PICO_GCC_TRIPLE})
# saved within the same cmake invocation
diff --git a/docs/index.h b/docs/index.h
index ded921d75..b760936c8 100644
--- a/docs/index.h
+++ b/docs/index.h
@@ -46,6 +46,7 @@
* \cond hardware_uart \defgroup hardware_uart hardware_uart \endcond
* \cond hardware_vreg \defgroup hardware_vreg hardware_vreg \endcond
* \cond hardware_watchdog \defgroup hardware_watchdog hardware_watchdog \endcond
+ * \cond hardware_xip_cache \defgroup hardware_xip_cache hardware_xip_cache \endcond
* \cond hardware_xosc \defgroup hardware_xosc hardware_xosc \endcond
* \cond hardware_powman hardware_powman
* \cond hardware_hazard3 hardware_hazard3
diff --git a/lib/cyw43-driver b/lib/cyw43-driver
index faf36381b..cf924bb04 160000
--- a/lib/cyw43-driver
+++ b/lib/cyw43-driver
@@ -1 +1 @@
-Subproject commit faf36381bad1f668a30172b6336c9a970966ef4c
+Subproject commit cf924bb04c8984675ca0fc2178f082e404e048c3
diff --git a/lib/tinyusb b/lib/tinyusb
index 423264289..5217cee5d 160000
--- a/lib/tinyusb
+++ b/lib/tinyusb
@@ -1 +1 @@
-Subproject commit 4232642899362fa5e9cf0dc59bad6f1f6d32c563
+Subproject commit 5217cee5de4cd555018da90f9f1bcc87fb1c1d3a
diff --git a/pico_sdk_init.cmake b/pico_sdk_init.cmake
index 48b44db38..b708b6349 100644
--- a/pico_sdk_init.cmake
+++ b/pico_sdk_init.cmake
@@ -75,6 +75,7 @@ if (NOT TARGET _pico_sdk_pre_init_marker)
PICO_SDK_POST_LIST_FILES
PICO_CONFIG_HEADER_FILES
PICO_RP2040_CONFIG_HEADER_FILES
+ PICO_BOARD_CMAKE_OVERRIDES
)
macro(pico_promote_common_scope_vars)
diff --git a/pico_sdk_version.cmake b/pico_sdk_version.cmake
index 37145ce85..27a215389 100644
--- a/pico_sdk_version.cmake
+++ b/pico_sdk_version.cmake
@@ -3,7 +3,7 @@
set(PICO_SDK_VERSION_MAJOR 2)
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, default=Current SDK minor version, group=pico_base
# PICO_CMAKE_CONFIG: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, default=Current SDK minor version, group=pico_base
-set(PICO_SDK_VERSION_MINOR 0)
+set(PICO_SDK_VERSION_MINOR 1)
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, default=Current SDK revision, group=pico_base
# PICO_CMAKE_CONFIG: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, default=Current SDK revision, group=pico_base
set(PICO_SDK_VERSION_REVISION 0)
diff --git a/src/BUILD.bazel b/src/BUILD.bazel
index 6f121f859..58d564ba2 100644
--- a/src/BUILD.bazel
+++ b/src/BUILD.bazel
@@ -14,6 +14,11 @@ alias(
"//src/common/hardware_claim:__pkg__",
"//src/common/pico_base_headers:__pkg__",
"//src/common/pico_binary_info:__pkg__",
+ # These libraries sometimes need the host version even though they live
+ # in rp2_common.
+ "//src/rp2_common/boot_bootrom_headers:__pkg__",
+ "//src/rp2_common/hardware_boot_lock:__pkg__",
+ "//src/rp2_common/pico_flash:__pkg__",
],
)
diff --git a/src/boards/BUILD.bazel b/src/boards/BUILD.bazel
index 94d1b3ed2..797f753ce 100644
--- a/src/boards/BUILD.bazel
+++ b/src/boards/BUILD.bazel
@@ -3,102 +3,15 @@ load("//bazel/util:multiple_choice_flag.bzl", "declare_flag_choices", "flag_choi
package(default_visibility = ["//visibility:public"])
-# Known board choices:
+# Find all boards.
+BOARD_CHOICE_FILES = glob(["include/boards/*.h"])
+
+# Extract just the name of the board.
BOARD_CHOICES = [
- "0xcb_helios",
- "adafruit_feather_rp2040_usb_host",
- "adafruit_feather_rp2040",
- "adafruit_itsybitsy_rp2040",
- "adafruit_kb2040",
- "adafruit_macropad_rp2040",
- "adafruit_qtpy_rp2040",
- "adafruit_trinkey_qt2040",
- "amethyst_fpga",
- "archi",
- "arduino_nano_rp2040_connect",
- "cytron_maker_pi_rp2040",
- "datanoisetv_rp2040_dsp",
- "defcon32_badge",
- "eetree_gamekit_rp2040",
- "garatronic_pybstick26_rp2040",
- "gen4_rp2350_24",
- "gen4_rp2350_24ct",
- "gen4_rp2350_24t",
- "gen4_rp2350_28",
- "gen4_rp2350_28ct",
- "gen4_rp2350_28t",
- "gen4_rp2350_32",
- "gen4_rp2350_32ct",
- "gen4_rp2350_32t",
- "gen4_rp2350_35",
- "gen4_rp2350_35ct",
- "gen4_rp2350_35t",
- "hellbender_2350A_devboard",
- "ilabs_challenger_rp2350_bconnect",
- "ilabs_challenger_rp2350_wifi_ble",
- "ilabs_opendec02",
- "melopero_perpetuo_rp2350_lora",
- "melopero_shake_rp2040",
- "metrotech_xerxes_rp2040",
- "net8086_usb_interposer",
- "none",
- "nullbits_bit_c_pro",
- "phyx_rick_tny_rp2350",
- "pi-plates_micropi",
- "pico_w",
- "pico",
- "pico2",
- "pimoroni_badger2040",
- "pimoroni_interstate75",
- "pimoroni_keybow2040",
- "pimoroni_motor2040",
- "pimoroni_pga2040",
- "pimoroni_pga2350",
- "pimoroni_pico_plus2_rp2350",
- "pimoroni_picolipo_16mb",
- "pimoroni_picolipo_4mb",
- "pimoroni_picosystem",
- "pimoroni_plasma2040",
- "pimoroni_plasma2350",
- "pimoroni_servo2040",
- "pimoroni_tiny2040_2mb",
- "pimoroni_tiny2040",
- "pimoroni_tiny2350",
- "pololu_3pi_2040_robot",
- "pololu_zumo_2040_robot",
- "seeed_xiao_rp2040",
- "seeed_xiao_rp2350",
- "solderparty_rp2040_stamp_carrier",
- "solderparty_rp2040_stamp_round_carrier",
- "solderparty_rp2040_stamp",
- "solderparty_rp2350_stamp_xl",
- "solderparty_rp2350_stamp",
- "sparkfun_micromod",
- "sparkfun_promicro_rp2350",
- "sparkfun_promicro",
- "sparkfun_thingplus",
- "switchscience_picossci2_conta_base",
- "switchscience_picossci2_dev_board",
- "switchscience_picossci2_micro",
- "switchscience_picossci2_rp2350_breakout",
- "switchscience_picossci2_tiny",
- "tinycircuits_thumby_color_rp2350",
- "vgaboard",
- "waveshare_rp2040_lcd_0.96",
- "waveshare_rp2040_lcd_1.28",
- "waveshare_rp2040_one",
- "waveshare_rp2040_plus_16mb",
- "waveshare_rp2040_plus_4mb",
- "waveshare_rp2040_zero",
- "weact_studio_rp2040_16mb",
- "weact_studio_rp2040_2mb",
- "weact_studio_rp2040_4mb",
- "weact_studio_rp2040_8mb",
- "wiznet_w5100s_evb_pico",
+ path.removeprefix("include/boards/").removesuffix(".h")
+ for path in BOARD_CHOICE_FILES
]
-BOARD_CHOICE_FILES = ["include/boards/" + c + ".h" for c in BOARD_CHOICES]
-
BOARD_CHOICE_MAP = {c: [":{}".format(c)] for c in BOARD_CHOICES}
# PICO_BUILD_DEFINE: PICO_BOARD, Name of board, type=string, default=CMake PICO_BOARD variable, group=pico_base
diff --git a/src/boards/include/boards/adafruit_feather_rp2350.h b/src/boards/include/boards/adafruit_feather_rp2350.h
new file mode 100644
index 000000000..20d77478d
--- /dev/null
+++ b/src/boards/include/boards/adafruit_feather_rp2350.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Scott Shawcroft for Adafruit Industries
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// This header may be included by other board headers as "boards/adafruit_feather_rp2350.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+
+#ifndef _BOARDS_ADAFRUIT_FEATHER_RP2350_H
+#define _BOARDS_ADAFRUIT_FEATHER_RP2350_H
+
+// For board detection
+#define ADAFRUIT_FEATHER_RP2350
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 1
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 7
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 21
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 1
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 2
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 3
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 22
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 23
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 20
+#endif
+
+// --- FLASH ---
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+#endif
diff --git a/src/boards/include/boards/amethyst_fpga.h b/src/boards/include/boards/amethyst_fpga.h
index d41dff41e..ea6b9a2d4 100644
--- a/src/boards/include/boards/amethyst_fpga.h
+++ b/src/boards/include/boards/amethyst_fpga.h
@@ -11,6 +11,8 @@
// FIXME delete this file before release (board file for Amethyst FPGA platform)
+// pico_cmake_set PICO_PLATFORM=rp2350
+
#ifndef _BOARDS_AMETHYST_FPGA_H
#define _BOARDS_AMETHYST_FPGA_H
diff --git a/src/boards/include/boards/datanoisetv_rp2350_dsp.h b/src/boards/include/boards/datanoisetv_rp2350_dsp.h
new file mode 100644
index 000000000..feb5792c0
--- /dev/null
+++ b/src/boards/include/boards/datanoisetv_rp2350_dsp.h
@@ -0,0 +1,64 @@
+ /*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the DatanoiseTV RP2350 DSP Board
+//
+// This header may be included by other board headers as "boards/datanoisetv_rp2350_dsp.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+
+#ifndef _BOARDS_DATANOISETV_RP2350_DSP_H
+#define _BOARDS_DATANOISETV_RP2350_DSP_H
+
+// For board detection
+#define DATANOISETV_RP2350_DSP
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 1
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 24
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 25
+#endif
+
+// -- FLASH --
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+// --- I2S ---
+#ifndef PICO_AUDIO_I2S_DATA_PIN
+#define PICO_AUDIO_I2S_DATA_PIN 16
+#endif
+#ifndef PICO_AUDIO_I2S_CLOCK_PIN_BASE
+#define PICO_AUDIO_I2S_CLOCK_PIN_BASE 17
+#endif
+
+#endif
diff --git a/src/boards/include/boards/defcon32_badge.h b/src/boards/include/boards/defcon32_badge.h
index 6e99ca58a..3466fc711 100644
--- a/src/boards/include/boards/defcon32_badge.h
+++ b/src/boards/include/boards/defcon32_badge.h
@@ -9,13 +9,6 @@
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
-// NOTE: since there is no UART on the badge, you should probably pass:
-// -DPICO_BOARD=defcon32_badge -DPICO_STDIO_USB=1 -DPICO_STDIO_UART+0
-// when building to set up stdio over USB CDC by default
-#define PICO_DEFAULT_UART 0
-#define PICO_DEFAULT_UART_TX_PIN 30
-#define PICO_DEFAULT_UART_RX_PIN 31
-
// pico_cmake_set PICO_PLATFORM=rp2350
#ifndef _BOARDS_DEFCON32_BADGE_H
@@ -56,6 +49,11 @@
#define DEFCON32_BADGE_IR_RX_PIN 27
#define DEFCON32_BADGE_IR_TX_PIN 28
+// --- UART ---
+// NOTE: since there is no UART on the badge, you should probably pass:
+// -DPICO_BOARD=defcon32_badge -DPICO_STDIO_USB=1 -DPICO_STDIO_UART=0
+// when building to set up stdio over USB CDC by default
+
// --- LED ---
// no PICO_DEFAULT_LED_PIN
#ifndef PICO_DEFAULT_WS2812_PIN
@@ -75,16 +73,16 @@
// --- SPI ---
#ifndef PICO_DEFAULT_SPI
-#define PICO_DEFAULT_SPI 0
+#define PICO_DEFAULT_SPI 1
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
#define PICO_DEFAULT_SPI_SCK_PIN DEFCON32_BADGE_SPI_CK_PIN
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
-#define PICO_DEFAULT_SPI_TX_PIN DEFCON32_BADGE_SPI_MISO_PIN
+#define PICO_DEFAULT_SPI_TX_PIN DEFCON32_BADGE_SPI_MOSI_PIN
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
-#define PICO_DEFAULT_SPI_RX_PIN DEFCON32_BADGE_SPI_MOSI_PIN
+#define PICO_DEFAULT_SPI_RX_PIN DEFCON32_BADGE_SPI_MISO_PIN
#endif
// multiple devices, so this doesn't make much sense
// no PICO_DEFAULT_SPI_CSN_PIN
@@ -110,6 +108,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_24.h b/src/boards/include/boards/gen4_rp2350_24.h
index c569c15cb..ec479653e 100644
--- a/src/boards/include/boards/gen4_rp2350_24.h
+++ b/src/boards/include/boards/gen4_rp2350_24.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_24
-#define _BOARDS_GEN4_RP2350_24
+#ifndef _BOARDS_GEN4_RP2350_24_H
+#define _BOARDS_GEN4_RP2350_24_H
// For board detection
#define GEN4_RP2350_24
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_24ct.h b/src/boards/include/boards/gen4_rp2350_24ct.h
index 2f6f15429..71b8f2e66 100644
--- a/src/boards/include/boards/gen4_rp2350_24ct.h
+++ b/src/boards/include/boards/gen4_rp2350_24ct.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_24CT
-#define _BOARDS_GEN4_RP2350_24CT
+#ifndef _BOARDS_GEN4_RP2350_24CT_H
+#define _BOARDS_GEN4_RP2350_24CT_H
// For board detection
#define GEN4_RP2350_24CT // CLB variants are exactly the same in operation
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_24t.h b/src/boards/include/boards/gen4_rp2350_24t.h
index 2d01017b8..df086fae5 100644
--- a/src/boards/include/boards/gen4_rp2350_24t.h
+++ b/src/boards/include/boards/gen4_rp2350_24t.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_24T
-#define _BOARDS_GEN4_RP2350_24T
+#ifndef _BOARDS_GEN4_RP2350_24T_H
+#define _BOARDS_GEN4_RP2350_24T_H
// For board detection
#define GEN4_RP2350_24T
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_28.h b/src/boards/include/boards/gen4_rp2350_28.h
index 804b2a99d..b460b8780 100644
--- a/src/boards/include/boards/gen4_rp2350_28.h
+++ b/src/boards/include/boards/gen4_rp2350_28.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_28
-#define _BOARDS_GEN4_RP2350_28
+#ifndef _BOARDS_GEN4_RP2350_28_H
+#define _BOARDS_GEN4_RP2350_28_H
// For board detection
#define GEN4_RP2350_28
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_28ct.h b/src/boards/include/boards/gen4_rp2350_28ct.h
index 1714ef115..11153e143 100644
--- a/src/boards/include/boards/gen4_rp2350_28ct.h
+++ b/src/boards/include/boards/gen4_rp2350_28ct.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_28CT
-#define _BOARDS_GEN4_RP2350_28CT
+#ifndef _BOARDS_GEN4_RP2350_28CT_H
+#define _BOARDS_GEN4_RP2350_28CT_H
// For board detection
#define GEN4_RP2350_28CT // CLB variants are exactly the same in operation
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_28t.h b/src/boards/include/boards/gen4_rp2350_28t.h
index b61c230e8..c948c9eb1 100644
--- a/src/boards/include/boards/gen4_rp2350_28t.h
+++ b/src/boards/include/boards/gen4_rp2350_28t.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_28T
-#define _BOARDS_GEN4_RP2350_28T
+#ifndef _BOARDS_GEN4_RP2350_28T_H
+#define _BOARDS_GEN4_RP2350_28T_H
// For board detection
#define GEN4_RP2350_28T
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_32.h b/src/boards/include/boards/gen4_rp2350_32.h
index 9660a4776..896937744 100644
--- a/src/boards/include/boards/gen4_rp2350_32.h
+++ b/src/boards/include/boards/gen4_rp2350_32.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_32
-#define _BOARDS_GEN4_RP2350_32
+#ifndef _BOARDS_GEN4_RP2350_32_H
+#define _BOARDS_GEN4_RP2350_32_H
// For board detection
#define GEN4_RP2350_32
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_32ct.h b/src/boards/include/boards/gen4_rp2350_32ct.h
index 9f883d4fb..0e137357e 100644
--- a/src/boards/include/boards/gen4_rp2350_32ct.h
+++ b/src/boards/include/boards/gen4_rp2350_32ct.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_32CT
-#define _BOARDS_GEN4_RP2350_32CT
+#ifndef _BOARDS_GEN4_RP2350_32CT_H
+#define _BOARDS_GEN4_RP2350_32CT_H
// For board detection
#define GEN4_RP2350_32CT // CLB variants are exactly the same in operation
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_32t.h b/src/boards/include/boards/gen4_rp2350_32t.h
index 04f4e0c0b..6280f0d7d 100644
--- a/src/boards/include/boards/gen4_rp2350_32t.h
+++ b/src/boards/include/boards/gen4_rp2350_32t.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_32T
-#define _BOARDS_GEN4_RP2350_32T
+#ifndef _BOARDS_GEN4_RP2350_32T_H
+#define _BOARDS_GEN4_RP2350_32T_H
// For board detection
#define GEN4_RP2350_32T
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_35.h b/src/boards/include/boards/gen4_rp2350_35.h
index d333c22f4..d26f53034 100644
--- a/src/boards/include/boards/gen4_rp2350_35.h
+++ b/src/boards/include/boards/gen4_rp2350_35.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_35
-#define _BOARDS_GEN4_RP2350_35
+#ifndef _BOARDS_GEN4_RP2350_35_H
+#define _BOARDS_GEN4_RP2350_35_H
// For board detection
#define GEN4_RP2350_35
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_35ct.h b/src/boards/include/boards/gen4_rp2350_35ct.h
index 778e1995e..8576ac503 100644
--- a/src/boards/include/boards/gen4_rp2350_35ct.h
+++ b/src/boards/include/boards/gen4_rp2350_35ct.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_35CT
-#define _BOARDS_GEN4_RP2350_35CT
+#ifndef _BOARDS_GEN4_RP2350_35CT_H
+#define _BOARDS_GEN4_RP2350_35CT_H
// For board detection
#define GEN4_RP2350_35CT // CLB variants are exactly the same in operation
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/gen4_rp2350_35t.h b/src/boards/include/boards/gen4_rp2350_35t.h
index 832337253..ee8cb2385 100644
--- a/src/boards/include/boards/gen4_rp2350_35t.h
+++ b/src/boards/include/boards/gen4_rp2350_35t.h
@@ -11,8 +11,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_GEN4_RP2350_35T
-#define _BOARDS_GEN4_RP2350_35T
+#ifndef _BOARDS_GEN4_RP2350_35T_H
+#define _BOARDS_GEN4_RP2350_35T_H
// For board detection
#define GEN4_RP2350_35T
@@ -76,6 +76,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/hellbender_0001.h b/src/boards/include/boards/hellbender_0001.h
new file mode 100644
index 000000000..9091f9124
--- /dev/null
+++ b/src/boards/include/boards/hellbender_0001.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_HELLBENDER_0001_H
+#define _BOARDS_HELLBENDER_0001_H
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+
+// For board detection
+#define HELLBENDER_0001
+
+// Pin aliases
+#define HELLBENDER_0001_BLACKBOX_FLASH_CS_PIN 0 // on qspi bus
+
+#define HELLBENDER_0001_IMU_CS_PIN 1 // also defined as PICO_DEFAULT_SPI_CSN_PIN
+#define HELLBENDER_0001_IMU_IRQ_PIN 22
+#define HELLBENDER_0001_IMU_CLKOUT_PIN 23
+
+#define HELLBENDER_0001_5V_EN_PIN 14
+#define HELLBENDER_0001_9V_EN_PIN 15
+
+#define HELLBENDER_0001_LED_BLUE_PIN 6 // also defined as PICO_DEFAULT_LED_PIN
+#define HELLBENDER_0001_LED_GREEN_PIN 7
+#define HELLBENDER_0001_BUZZER_PIN 5
+
+#define HELLBENDER_0001_GNSS_UART_TX_PIN 8
+#define HELLBENDER_0001_GNSS_UART_RX_PIN 9
+
+#define HELLBENDER_0001_DVTX_UART_TX_PIN 12
+#define HELLBENDER_0001_DVTX_UART_RX_PIN 13
+#define HELLBENDER_0001_DVTX_SBUS_PIN 36
+
+#define HELLBENDER_0001_ESC_TELEM_RX_PIN 37
+
+#define HELLBENDER_0001_OFFBOARD_WS2812_PIN 38
+#define HELLBENDER_0001_ONBOARD_WS2812_PIN 39 // also defined as PICO_DEFAULT_WS2812_PIN
+
+#define HELLBENDER_0001_SPARE_UART_TX_PIN 34
+#define HELLBENDER_0001_SPARE_UART_RX_PIN 35
+
+#define HELLBENDER_0001_I2C_CON_SDA_PIN 10
+#define HELLBENDER_0001_I2C_CON_SCL_PIN 11
+
+#define HELLBENDER_0001_FTRX_TX_PIN 20
+#define HELLBENDER_0001_FTRX_RX_PIN 21
+
+#define HELLBENDER_0001_SD_OSD_SPI_TX_PIN 27
+#define HELLBENDER_0001_SD_OSD_SPI_RX_PIN 24
+#define HELLBENDER_0001_SD_OSD_SPI_SCK_PIN 26
+#define HELLBENDER_0001_OSD_CS_PIN 17
+#define HELLBENDER_0001_SD_CS_PIN 25
+
+#define HELLBENDER_0001_DSHOT1_PIN 28
+#define HELLBENDER_0001_DSHOT2_PIN 29
+#define HELLBENDER_0001_DSHOT3_PIN 30
+#define HELLBENDER_0001_DSHOT4_PIN 31
+
+#define HELLBENDER_0001_GPIO_SPARE1_PIN 32
+#define HELLBENDER_0001_GPIO_SPARE2_PIN 33
+#define HELLBENDER_0001_GPIO_SPARE3_PIN 47
+
+#define HELLBENDER_0001_VBAT_SENSE_PIN 40
+#define HELLBENDER_0001_CURR_SENSE_PIN 41
+#define HELLBENDER_0001_SPARE_ADC_PIN 42
+
+
+// --- UART ---
+// Note, conflicts with HSTX range
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 12
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 13
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 6
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 39
+#endif
+
+// --- I2C ---
+// Default I2C is connected to barometer
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 44
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 45
+#endif
+
+// --- SPI ---
+// Default SPI is connected to IMU
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 2
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 3
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 4
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 1
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+#define HELLBENDER_0001_BLACKBOX_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350B 1
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+#endif
diff --git a/src/boards/include/boards/hellbender_2350A_devboard.h b/src/boards/include/boards/hellbender_2350A_devboard.h
index 03895e1b4..63753bcca 100644
--- a/src/boards/include/boards/hellbender_2350A_devboard.h
+++ b/src/boards/include/boards/hellbender_2350A_devboard.h
@@ -9,8 +9,8 @@
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
-#ifndef _BOARDS_HB_2350A_H
-#define _BOARDS_HB_2350A_H
+#ifndef _BOARDS_HELLBENDER_2350A_DEVBOARD_H
+#define _BOARDS_HELLBENDER_2350A_DEVBOARD_H
// pico_cmake_set PICO_PLATFORM=rp2350
@@ -91,6 +91,7 @@
// --- RP2350 VARIANT ---
#define PICO_RP2350A 1
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/ilabs_challenger_rp2350_bconnect.h b/src/boards/include/boards/ilabs_challenger_rp2350_bconnect.h
index b0bbebe28..92d8960b8 100644
--- a/src/boards/include/boards/ilabs_challenger_rp2350_bconnect.h
+++ b/src/boards/include/boards/ilabs_challenger_rp2350_bconnect.h
@@ -13,8 +13,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_CHALLENGER_RP2350_BCONNECT_H
-#define _BOARDS_CHALLENGER_RP2350_BCONNECT_H
+#ifndef _BOARDS_ILABS_CHALLENGER_RP2350_BCONNECT_H
+#define _BOARDS_ILABS_CHALLENGER_RP2350_BCONNECT_H
// For board detection
#define ILABS_CHALLENGER_RP2350_BCONNECT
@@ -83,10 +83,7 @@
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
#endif
-#ifndef PICO_RP2040_B0_SUPPORTED
-#define PICO_RP2040_B0_SUPPORTED 1
-#endif
-
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/ilabs_challenger_rp2350_wifi_ble.h b/src/boards/include/boards/ilabs_challenger_rp2350_wifi_ble.h
index 29ac3df3e..1278209b8 100644
--- a/src/boards/include/boards/ilabs_challenger_rp2350_wifi_ble.h
+++ b/src/boards/include/boards/ilabs_challenger_rp2350_wifi_ble.h
@@ -13,8 +13,8 @@
// pico_cmake_set PICO_PLATFORM=rp2350
-#ifndef _BOARDS_CHALLENGER_RP2350_WIFI_BLE_H
-#define _BOARDS_CHALLENGER_RP2350_WIFI_BLE_H
+#ifndef _BOARDS_ILABS_CHALLENGER_RP2350_WIFI_BLE_H
+#define _BOARDS_ILABS_CHALLENGER_RP2350_WIFI_BLE_H
// For board detection
#define ILABS_CHALLENGER_RP2350_WIFI_BLE
@@ -80,10 +80,7 @@
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
#endif
-#ifndef PICO_RP2040_B0_SUPPORTED
-#define PICO_RP2040_B0_SUPPORTED 1
-#endif
-
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/machdyne_werkzeug.h b/src/boards/include/boards/machdyne_werkzeug.h
new file mode 100644
index 000000000..8b45829b7
--- /dev/null
+++ b/src/boards/include/boards/machdyne_werkzeug.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// pico_cmake_set PICO_PLATFORM=rp2040
+
+#ifndef _BOARDS_MACHDYNE_WERKZEUG_H
+#define _BOARDS_MACHDYNE_WERKZEUG_H
+
+// For board detection
+#define MACHDYNE_WERKZEUG
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 20
+#define PICO_DEFAULT_LED_PIN_INVERTED 1
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (1 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (1 * 1024 * 1024)
+#endif
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 1
+#endif
+
+#endif
diff --git a/src/boards/include/boards/melopero_perpetuo_rp2350_lora.h b/src/boards/include/boards/melopero_perpetuo_rp2350_lora.h
index cc358de34..e86492b39 100644
--- a/src/boards/include/boards/melopero_perpetuo_rp2350_lora.h
+++ b/src/boards/include/boards/melopero_perpetuo_rp2350_lora.h
@@ -82,6 +82,7 @@
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/metrotech_xerxes_rp2040.h b/src/boards/include/boards/metrotech_xerxes_rp2040.h
index a78e3ea9a..a91d893ff 100644
--- a/src/boards/include/boards/metrotech_xerxes_rp2040.h
+++ b/src/boards/include/boards/metrotech_xerxes_rp2040.h
@@ -14,67 +14,65 @@
#ifndef _BOARDS_METROTECH_XERXES_RP2040_H
#define _BOARDS_METROTECH_XERXES_RP2040_H
-
-#define USR_SW_PIN 18
-#define USR_BTN_PIN 24
-#define USR_LED_PIN 25
-
-#define UART1_TX_PIN 8
-#define UART1_RX_PIN 9
-
-#define UART0_TX_PIN 16
-#define UART0_RX_PIN 17
-
-#define SPI0_MISO_PIN 0
-#define SPI0_CSN_PIN 1
-#define SPI0_CLK_PIN 2
-#define SPI0_MOSI_PIN 3
-
-#define I2C0_SDA_PIN 4
-#define I2C0_SCL_PIN 5
-
-#define EXT_3V3_EN_PIN 6
-
-#define RS_EN_PIN 19
-#define RS_TX_PIN UART0_TX_PIN
-#define RS_RX_PIN UART0_RX_PIN
-
-#define ADC0_PIN 26 // ADC0 and PWM5_A share the same pin
-#define ADC1_PIN 27 // ADC1 and PWM5_B share the same pin
-#define ADC2_PIN 28 // ADC2 and PWM6_A share the same pin
-#define ADC3_PIN 29 // ADC3 and PWM6_B share the same pin
-
-#define TMP0_PIN 22 // TMP0 and I2C1 share the same pin
-#define TMP1_PIN 23 // TMP1 and I2C1 share the same pin
-
-#define I2C1_SDA_PIN 22 // I2C1 and TMP0 share the same pin
-#define I2C1_SCL_PIN 23 // I2C1 and TMP1 share the same pin
-
-#define PWM0_A_PIN 0 // PWM0_A and SPI0_MISO share the same pin
-#define PWM0_B_PIN 1 // PWM0_B and SPI0_CSN share the same pin
-#define PWM1_A_PIN 2 // PWM1_A and SPI0_CLK share the same pin
-#define PWM1_B_PIN 3 // PWM1_B and SPI0_MOSI share the same pin
-#define PWM2_A_PIN 4 // PWM2_A and I2C0_SDA share the same pin
-#define PWM2_B_PIN 5 // PWM2_B and I2C0_SCL share the same pin
-#define PWM3_A_PIN 22 // PWM3_A and TMP0 share the same pin
-#define PWM3_B_PIN 23 // PWM3_B and TMP1 share the same pin
-#define PWM4_A_PIN 24 // PWM4_A and USR_BTN share the same pin
-#define PWM4_B_PIN 25 // PWM4_B and USR_LED share the same pin
-#define PWM5_A_PIN 26 // PWM5_A and ADC0 share the same pin
-#define PWM5_B_PIN 27 // PWM5_B and ADC1 share the same pin
-#define PWM6_A_PIN 28 // PWM6_A and ADC2 share the same pin
-#define PWM6_B_PIN 29 // PWM6_B and ADC3 share the same pin
-
-#define CLK_GPIN1_PIN 22 // CLK_GPIN1 and TMP0 share the same pin
-#define CLK_GPOUT1_PIN 23 // CLK_GPOUT1 and TMP1 share the same pin
+#define USR_SW_PIN 18
+#define USR_BTN_PIN 24
+#define USR_LED_PIN 25
+
+#define UART1_TX_PIN 8
+#define UART1_RX_PIN 9
+
+#define UART0_TX_PIN 16
+#define UART0_RX_PIN 17
+
+#define SPI0_MISO_PIN 0
+#define SPI0_CSN_PIN 1
+#define SPI0_CLK_PIN 2
+#define SPI0_MOSI_PIN 3
+
+#define I2C0_SDA_PIN 4
+#define I2C0_SCL_PIN 5
+
+#define EXT_3V3_EN_PIN 6
+
+#define RS_EN_PIN 19
+#define RS_TX_PIN UART0_TX_PIN
+#define RS_RX_PIN UART0_RX_PIN
+
+#define ADC0_PIN 26 // ADC0 and PWM5_A share the same pin
+#define ADC1_PIN 27 // ADC1 and PWM5_B share the same pin
+#define ADC2_PIN 28 // ADC2 and PWM6_A share the same pin
+#define ADC3_PIN 29 // ADC3 and PWM6_B share the same pin
+
+#define TMP0_PIN 22 // TMP0 and I2C1 share the same pin
+#define TMP1_PIN 23 // TMP1 and I2C1 share the same pin
+
+#define I2C1_SDA_PIN 22 // I2C1 and TMP0 share the same pin
+#define I2C1_SCL_PIN 23 // I2C1 and TMP1 share the same pin
+
+#define PWM0_A_PIN 0 // PWM0_A and SPI0_MISO share the same pin
+#define PWM0_B_PIN 1 // PWM0_B and SPI0_CSN share the same pin
+#define PWM1_A_PIN 2 // PWM1_A and SPI0_CLK share the same pin
+#define PWM1_B_PIN 3 // PWM1_B and SPI0_MOSI share the same pin
+#define PWM2_A_PIN 4 // PWM2_A and I2C0_SDA share the same pin
+#define PWM2_B_PIN 5 // PWM2_B and I2C0_SCL share the same pin
+#define PWM3_A_PIN 22 // PWM3_A and TMP0 share the same pin
+#define PWM3_B_PIN 23 // PWM3_B and TMP1 share the same pin
+#define PWM4_A_PIN 24 // PWM4_A and USR_BTN share the same pin
+#define PWM4_B_PIN 25 // PWM4_B and USR_LED share the same pin
+#define PWM5_A_PIN 26 // PWM5_A and ADC0 share the same pin
+#define PWM5_B_PIN 27 // PWM5_B and ADC1 share the same pin
+#define PWM6_A_PIN 28 // PWM6_A and ADC2 share the same pin
+#define PWM6_B_PIN 29 // PWM6_B and ADC3 share the same pin
+
+#define CLK_GPIN1_PIN 22 // CLK_GPIN1 and TMP0 share the same pin
+#define CLK_GPOUT1_PIN 23 // CLK_GPOUT1 and TMP1 share the same pin
/// @brief Mask of pins that are used by the shield and not used by the board, eq. 0x3fc0033f
-#define SHIELD_MASK 1 << SPI0_MISO_PIN | 1 << SPI0_CSN_PIN | 1 << SPI0_CLK_PIN | 1 << SPI0_MOSI_PIN | \
- 1 << I2C0_SDA_PIN | 1 << I2C0_SCL_PIN | \
- 1 << UART1_TX_PIN | 1 << UART1_RX_PIN | \
- 1 << ADC0_PIN | 1 << ADC1_PIN | 1 << ADC2_PIN | 1 << ADC3_PIN | \
- 1 << TMP0_PIN | 1 << TMP1_PIN
-
+#define SHIELD_MASK 1 << SPI0_MISO_PIN | 1 << SPI0_CSN_PIN | 1 << SPI0_CLK_PIN | 1 << SPI0_MOSI_PIN | \
+ 1 << I2C0_SDA_PIN | 1 << I2C0_SCL_PIN | \
+ 1 << UART1_TX_PIN | 1 << UART1_RX_PIN | \
+ 1 << ADC0_PIN | 1 << ADC1_PIN | 1 << ADC2_PIN | 1 << ADC3_PIN | \
+ 1 << TMP0_PIN | 1 << TMP1_PIN
// For board detection
#define XERXES_RP2040
@@ -127,22 +125,21 @@
// --- FLASH ---
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
-#ifndef __CLKDIV
+#ifndef __CLKDIV
#define __CLKDIV 4
#endif // !__CLKDIV
#ifndef PICO_FLASH_SPI_CLKDIV
/**
* @brief divisor for SPI clock (default 4), must be divisible by 2
- *
- * This is critical for some flash chips, and can be set to 4 for some,
+ *
+ * This is critical for some flash chips, and can be set to 4 for some,
* but needs to be at least 32 for others. Set using -DCLKDIV= in cmake.
* @note Increasing this value will help with BOOTLOOPs, but will slow down the flash chip.
*/
#define PICO_FLASH_SPI_CLKDIV __CLKDIV
#endif // !PICO_FLASH_SPI_CLKDIV
-
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 16
#endif // !PICO_XOSC_STARTUP_DELAY_MULTIPLIER
@@ -151,20 +148,15 @@
#ifndef PICO_FLASH_SIZE_BYTES
/**
* @brief 16MiB, Flash size in bytes
- *
+ *
* This is the size of the flash chip on the board, not the size of the flash chip that is used for the bootloader.
*/
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif // !PICO_FLASH_SIZE_BYTES
// All boards have B1 RP2040
-#ifndef PICO_RP2040_B0_SUPPORTED
-#define PICO_RP2040_B0_SUPPORTED 0
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
#endif // !PICO_RP2040_B0_SUPPORTED
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
#endif // _BOARDS_METROTECH_XERXES_RP2040_H
\ No newline at end of file
diff --git a/src/boards/include/boards/phyx_rick_tny_rp2350.h b/src/boards/include/boards/phyx_rick_tny_rp2350.h
index eb9e678f1..7012ac141 100644
--- a/src/boards/include/boards/phyx_rick_tny_rp2350.h
+++ b/src/boards/include/boards/phyx_rick_tny_rp2350.h
@@ -42,7 +42,7 @@
// --- I2C ---
#ifndef PICO_DEFAULT_I2C
-#define PICO_DEFAULT_I2C 0
+#define PICO_DEFAULT_I2C 1
#endif
#ifndef PICO_DEFAULT_I2C_SDA_PIN
#define PICO_DEFAULT_I2C_SDA_PIN 6
@@ -80,6 +80,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/pico2.h b/src/boards/include/boards/pico2.h
index 4146f397c..4dbb232d2 100644
--- a/src/boards/include/boards/pico2.h
+++ b/src/boards/include/boards/pico2.h
@@ -9,7 +9,7 @@
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
-// This header may be included by other board headers as "boards/pico.h"
+// This header may be included by other board headers as "boards/pico2.h"
// pico_cmake_set PICO_PLATFORM=rp2350
@@ -93,6 +93,7 @@
#define PICO_VSYS_PIN 29
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/pico2_w.h b/src/boards/include/boards/pico2_w.h
new file mode 100644
index 000000000..42acdc4cc
--- /dev/null
+++ b/src/boards/include/boards/pico2_w.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// This header may be included by other board headers as "boards/pico2_w.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+// pico_cmake_set PICO_CYW43_SUPPORTED = 1
+
+#ifndef _BOARDS_PICO2_W_H
+#define _BOARDS_PICO2_W_H
+
+// For board detection
+#define RASPBERRYPI_PICO2_W
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 1
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
+// no PICO_DEFAULT_WS2812_PIN
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (4 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
+#endif
+// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
+// note the SMSP mode pin is on WL_GPIO1
+
+#ifndef CYW43_WL_GPIO_COUNT
+#define CYW43_WL_GPIO_COUNT 3
+#endif
+
+#ifndef CYW43_WL_GPIO_LED_PIN
+#define CYW43_WL_GPIO_LED_PIN 0
+#endif
+
+// If CYW43_WL_GPIO_VBUS_PIN is defined then a CYW43 GPIO has to be used to read VBUS.
+// This can be passed to cyw43_arch_gpio_get to determine if the device is battery powered.
+// PICO_VBUS_PIN and CYW43_WL_GPIO_VBUS_PIN should not both be defined.
+#ifndef CYW43_WL_GPIO_VBUS_PIN
+#define CYW43_WL_GPIO_VBUS_PIN 2
+#endif
+
+// If CYW43_USES_VSYS_PIN is defined then CYW43 uses the VSYS GPIO (defined by PICO_VSYS_PIN) for other purposes.
+// If this is the case, to use the VSYS GPIO it's necessary to ensure CYW43 is not using it.
+// This can be achieved by wrapping the use of the VSYS GPIO in cyw43_thread_enter / cyw43_thread_exit.
+#ifndef CYW43_USES_VSYS_PIN
+#define CYW43_USES_VSYS_PIN 1
+#endif
+
+// The GPIO Pin used to monitor VSYS. Typically you would use this with ADC.
+// There is an example in adc/read_vsys in pico-examples.
+#ifndef PICO_VSYS_PIN
+#define PICO_VSYS_PIN 29
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+// cyw43 SPI pins can't be changed at runtime
+#ifndef CYW43_PIN_WL_DYNAMIC
+#define CYW43_PIN_WL_DYNAMIC 0
+#endif
+
+// gpio pin to power up the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
+#define CYW43_DEFAULT_PIN_WL_REG_ON 23u
+#endif
+
+// gpio pin for spi data out to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
+#define CYW43_DEFAULT_PIN_WL_DATA_OUT 24u
+#endif
+
+// gpio pin for spi data in from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
+#define CYW43_DEFAULT_PIN_WL_DATA_IN 24u
+#endif
+
+// gpio (irq) pin for the irq line from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
+#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 24u
+#endif
+
+// gpio pin for the spi clock line to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
+#define CYW43_DEFAULT_PIN_WL_CLOCK 29u
+#endif
+
+// gpio pin for the spi chip select to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CS
+#define CYW43_DEFAULT_PIN_WL_CS 25u
+#endif
+
+#endif
diff --git a/src/boards/include/boards/pico_w.h b/src/boards/include/boards/pico_w.h
index 9e7464cef..250662f1b 100644
--- a/src/boards/include/boards/pico_w.h
+++ b/src/boards/include/boards/pico_w.h
@@ -86,14 +86,6 @@
#define PICO_RP2040_B1_SUPPORTED 0
#endif
-#ifndef CYW43_PIN_WL_HOST_WAKE
-#define CYW43_PIN_WL_HOST_WAKE 24
-#endif
-
-#ifndef CYW43_PIN_WL_REG_ON
-#define CYW43_PIN_WL_REG_ON 23
-#endif
-
#ifndef CYW43_WL_GPIO_COUNT
#define CYW43_WL_GPIO_COUNT 3
#endif
@@ -122,4 +114,39 @@
#define PICO_VSYS_PIN 29
#endif
+// cyw43 SPI pins can't be changed at runtime
+#ifndef CYW43_PIN_WL_DYNAMIC
+#define CYW43_PIN_WL_DYNAMIC 0
+#endif
+
+// gpio pin to power up the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
+#define CYW43_DEFAULT_PIN_WL_REG_ON 23u
+#endif
+
+// gpio pin for spi data out to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
+#define CYW43_DEFAULT_PIN_WL_DATA_OUT 24u
+#endif
+
+// gpio pin for spi data in from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
+#define CYW43_DEFAULT_PIN_WL_DATA_IN 24u
+#endif
+
+// gpio (irq) pin for the irq line from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
+#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 24u
+#endif
+
+// gpio pin for the spi clock line to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
+#define CYW43_DEFAULT_PIN_WL_CLOCK 29u
+#endif
+
+// gpio pin for the spi chip select to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CS
+#define CYW43_DEFAULT_PIN_WL_CS 25u
+#endif
+
#endif
diff --git a/src/boards/include/boards/pimoroni_pga2350.h b/src/boards/include/boards/pimoroni_pga2350.h
index 9690f130c..f4f0a3d2a 100644
--- a/src/boards/include/boards/pimoroni_pga2350.h
+++ b/src/boards/include/boards/pimoroni_pga2350.h
@@ -85,6 +85,7 @@
// no PICO_VBUS_PIN
// no PICO_VSYS_PIN
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h b/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h
index 13328f308..34c5fb38f 100644
--- a/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h
+++ b/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h
@@ -20,12 +20,12 @@
#define PIMORONI_PICO_PLUS2_RP2350
// --- BOARD SPECIFIC ---
-#define SPICE_SPI 0
-#define SPICE_TX_MISO_PIN 32
-#define SPICE_RX_CS_PIN 33
-#define SPICE_NETLIGHT_SCK_PIN 34
-#define SPICE_RESET_MOSI_PIN 35
-#define SPICE_PWRKEY_BL_PIN 36
+#define SPCE_SPI 0
+#define SPCE_TX_MISO_PIN 32
+#define SPCE_RX_CS_PIN 33
+#define SPCE_NETLIGHT_SCK_PIN 34
+#define SPCE_RESET_MOSI_PIN 35
+#define SPCE_PWRKEY_BL_PIN 36
#define PIMORONI_PICO_PLUS2_USER_SW_PIN 45
#define PIMORONI_PICO_PLUS2_PSRAM_CS_PIN 47
@@ -63,16 +63,16 @@
#define PICO_DEFAULT_SPI 0
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
-#define PICO_DEFAULT_SPI_SCK_PIN SPICE_NETLIGHT_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN SPCE_NETLIGHT_SCK_PIN
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
-#define PICO_DEFAULT_SPI_TX_PIN SPICE_RESET_MOSI_PIN
+#define PICO_DEFAULT_SPI_TX_PIN SPCE_RESET_MOSI_PIN
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
-#define PICO_DEFAULT_SPI_RX_PIN SPICE_TX_MISO_PIN
+#define PICO_DEFAULT_SPI_RX_PIN SPCE_TX_MISO_PIN
#endif
#ifndef PICO_DEFAULT_SPI_CSN_PIN
-#define PICO_DEFAULT_SPI_CSN_PIN SPICE_RX_CS_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN SPCE_RX_CS_PIN
#endif
// --- FLASH ---
@@ -99,6 +99,7 @@
#define PICO_VSYS_PIN 43
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h b/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h
new file mode 100644
index 000000000..ba3c0e56c
--- /dev/null
+++ b/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// This header may be included by other board headers as "boards/pimoroni_pico_plus2_w_rp2350.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+// pico_cmake_set PICO_CYW43_SUPPORTED = 1
+
+#ifndef _BOARDS_PIMORONI_PICO_PLUS2_W_RP2350_H
+#define _BOARDS_PIMORONI_PICO_PLUS2_W_RP2350_H
+
+// For board detection
+#define PIMORONI_PICO_PLUS2_W_RP2350
+
+// --- BOARD SPECIFIC ---
+#define PIMORONI_PICO_PLUS2_W_USER_SW_PIN 45
+#define PIMORONI_PICO_PLUS2_W_PSRAM_CS_PIN 47
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
+// no PICO_DEFAULT_WS2812_PIN
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (16 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+#endif
+
+// The GPIO Pin used to monitor VSYS. Typically you would use this with ADC.
+// There is an example in adc/read_vsys in pico-examples.
+#ifndef PICO_VSYS_PIN
+#define PICO_VSYS_PIN 43
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+// --- CYW43 ---
+
+// gpio pin to power up the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
+#define CYW43_DEFAULT_PIN_WL_REG_ON 23
+#endif
+
+// gpio pin for spi data out to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
+#define CYW43_DEFAULT_PIN_WL_DATA_OUT 24
+#endif
+
+// gpio pin for spi data in from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
+#define CYW43_DEFAULT_PIN_WL_DATA_IN 24
+#endif
+
+// gpio (irq) pin for the irq line from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
+#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 24
+#endif
+
+// gpio pin for the spi clock line to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
+#define CYW43_DEFAULT_PIN_WL_CLOCK 29
+#endif
+
+// gpio pin for the spi chip select to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CS
+#define CYW43_DEFAULT_PIN_WL_CS 25u
+#endif
+
+#ifndef CYW43_WL_GPIO_COUNT
+#define CYW43_WL_GPIO_COUNT 3
+#endif
+
+#ifndef CYW43_WL_GPIO_LED_PIN
+#define CYW43_WL_GPIO_LED_PIN 0
+#endif
+
+// If CYW43_WL_GPIO_VBUS_PIN is defined then a CYW43 GPIO has to be used to read VBUS.
+// This can be passed to cyw43_arch_gpio_get to determine if the device is battery powered.
+// PICO_VBUS_PIN and CYW43_WL_GPIO_VBUS_PIN should not both be defined.
+#ifndef CYW43_WL_GPIO_VBUS_PIN
+#define CYW43_WL_GPIO_VBUS_PIN 2
+#endif
+
+// If CYW43_USES_VSYS_PIN is defined then CYW43 uses the VSYS GPIO (defined by PICO_VSYS_PIN) for other purposes.
+// If this is the case, to use the VSYS GPIO it's necessary to ensure CYW43 is not using it.
+// This can be achieved by wrapping the use of the VSYS GPIO in cyw43_thread_enter / cyw43_thread_exit.
+#ifndef CYW43_USES_VSYS_PIN
+#define CYW43_USES_VSYS_PIN 1
+#endif
+
+#endif
diff --git a/src/boards/include/boards/pimoroni_plasma2350.h b/src/boards/include/boards/pimoroni_plasma2350.h
index 9fb63eb8f..7525a8a84 100644
--- a/src/boards/include/boards/pimoroni_plasma2350.h
+++ b/src/boards/include/boards/pimoroni_plasma2350.h
@@ -20,12 +20,12 @@
#define PIMORONI_PLASMA2350
// --- BOARD SPECIFIC ---
-#define SPICE_SPI 0
-#define SPICE_TX_MISO_PIN 8
-#define SPICE_RX_CS_PIN 9
-#define SPICE_NETLIGHT_SCK_PIN 10
-#define SPICE_RESET_MOSI_PIN 11
-#define SPICE_PWRKEY_BL_PIN 7
+#define SPCE_SPI 0
+#define SPCE_TX_MISO_PIN 8
+#define SPCE_RX_CS_PIN 9
+#define SPCE_NETLIGHT_SCK_PIN 10
+#define SPCE_RESET_MOSI_PIN 11
+#define SPCE_PWRKEY_BL_PIN 7
#define PLASMA2350_SW_A_PIN 12
@@ -60,7 +60,7 @@
// --- LED ---
#ifndef PICO_DEFAULT_LED_PIN
-#define PICO_DEFAULT_LED_PIN TINY2350_LED_G_PIN
+#define PICO_DEFAULT_LED_PIN PLASMA2350_LED_G_PIN
#endif
// no PICO_DEFAULT_WS2812_PIN
@@ -82,19 +82,19 @@
// --- SPI ---
#ifndef PICO_DEFAULT_SPI
-#define PICO_DEFAULT_SPI 0
+#define PICO_DEFAULT_SPI 1
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
-#define PICO_DEFAULT_SPI_SCK_PIN SPICE_NETLIGHT_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN SPCE_NETLIGHT_SCK_PIN
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
-#define PICO_DEFAULT_SPI_TX_PIN SPICE_RESET_MOSI_PIN
+#define PICO_DEFAULT_SPI_TX_PIN SPCE_RESET_MOSI_PIN
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
-#define PICO_DEFAULT_SPI_RX_PIN SPICE_TX_MISO_PIN
+#define PICO_DEFAULT_SPI_RX_PIN SPCE_TX_MISO_PIN
#endif
#ifndef PICO_DEFAULT_SPI_CSN_PIN
-#define PICO_DEFAULT_SPI_CSN_PIN SPICE_RX_CS_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN SPCE_RX_CS_PIN
#endif
// --- FLASH ---
@@ -104,11 +104,12 @@
#define PICO_FLASH_SPI_CLKDIV 2
#endif
-// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (4 * 1024 * 1024)
#ifndef PICO_FLASH_SIZE_BYTES
-#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/pimoroni_tiny2350.h b/src/boards/include/boards/pimoroni_tiny2350.h
index f6472a619..bf00cbdb9 100644
--- a/src/boards/include/boards/pimoroni_tiny2350.h
+++ b/src/boards/include/boards/pimoroni_tiny2350.h
@@ -84,11 +84,12 @@
#define PICO_FLASH_SPI_CLKDIV 2
#endif
-// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (4 * 1024 * 1024)
#ifndef PICO_FLASH_SIZE_BYTES
-#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/seeed_xiao_rp2350.h b/src/boards/include/boards/seeed_xiao_rp2350.h
index 5c5859402..3390dedcc 100644
--- a/src/boards/include/boards/seeed_xiao_rp2350.h
+++ b/src/boards/include/boards/seeed_xiao_rp2350.h
@@ -142,6 +142,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/solderparty_rp2350_stamp.h b/src/boards/include/boards/solderparty_rp2350_stamp.h
index fee982c8c..bb2fd7b52 100644
--- a/src/boards/include/boards/solderparty_rp2350_stamp.h
+++ b/src/boards/include/boards/solderparty_rp2350_stamp.h
@@ -78,10 +78,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
-#ifndef PICO_RP2040_B0_SUPPORTED
-#define PICO_RP2040_B0_SUPPORTED 1
-#endif
-
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/solderparty_rp2350_stamp_xl.h b/src/boards/include/boards/solderparty_rp2350_stamp_xl.h
index 97fa0bf18..33233f7d6 100644
--- a/src/boards/include/boards/solderparty_rp2350_stamp_xl.h
+++ b/src/boards/include/boards/solderparty_rp2350_stamp_xl.h
@@ -78,10 +78,7 @@
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
-#ifndef PICO_RP2040_B0_SUPPORTED
-#define PICO_RP2040_B0_SUPPORTED 1
-#endif
-
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/sparkfun_promicro_rp2350.h b/src/boards/include/boards/sparkfun_promicro_rp2350.h
index fd12de506..8709e8dca 100644
--- a/src/boards/include/boards/sparkfun_promicro_rp2350.h
+++ b/src/boards/include/boards/sparkfun_promicro_rp2350.h
@@ -81,6 +81,7 @@
// --- RP2350 VARIANT ---
#define PICO_RP2350A 1
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/sparkfun_thingplus_rp2350.h b/src/boards/include/boards/sparkfun_thingplus_rp2350.h
new file mode 100644
index 000000000..d023f943e
--- /dev/null
+++ b/src/boards/include/boards/sparkfun_thingplus_rp2350.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+// Board definition for the SparkFun RP2350 Thing Plus
+//
+// This header may be included by other board headers as "boards/sparkfun_thingplus_rp2350.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+// pico_cmake_set PICO_CYW43_SUPPORTED = 1
+
+#ifndef _BOARDS_SPARKFUN_THINGPLUS_RP2350_H
+#define _BOARDS_SPARKFUN_THINGPLUS_RP2350_H
+
+// For board detection
+#define SPARKFUN_THINGPLUS_RP2350
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 1
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 14
+#endif
+
+// --- I2C --- Qwiic connector is on these pins
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 1
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 6
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 7
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 2
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 3
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 4
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 5
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (16 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+#endif
+
+// The thing plus has a SD Card.
+#ifndef PICO_SD_CLK_PIN
+#define PICO_SD_CLK_PIN 2
+#endif
+#ifndef PICO_SD_CMD_PIN
+#define PICO_SD_CMD_PIN 3
+#endif
+#ifndef PICO_SD_DAT0_PIN
+#define PICO_SD_DAT0_PIN 4
+#endif
+#ifndef PICO_SD_DAT3_PIN
+#define PICO_SD_DAT3_PIN 8 // DAT3 of the SD card is the chip select pin
+#endif
+#ifndef PICO_SD_DAT_PIN_COUNT
+#define PICO_SD_DAT_PIN_COUNT 1
+#endif
+
+#ifndef CYW43_WL_GPIO_COUNT
+#define CYW43_WL_GPIO_COUNT 3
+#endif
+
+#ifndef CYW43_WL_GPIO_LED_PIN
+#define CYW43_WL_GPIO_LED_PIN 0
+#endif
+
+// If CYW43_WL_GPIO_VBUS_PIN is defined then a CYW43 GPIO has to be used to read VBUS.
+// This can be passed to cyw43_arch_gpio_get to determine if the device is battery powered.
+// PICO_VBUS_PIN and CYW43_WL_GPIO_VBUS_PIN should not both be defined.
+#ifndef CYW43_WL_GPIO_VBUS_PIN
+#define CYW43_WL_GPIO_VBUS_PIN 2
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+// cyw43 SPI pins can't be changed at runtime
+#ifndef CYW43_PIN_WL_DYNAMIC
+#define CYW43_PIN_WL_DYNAMIC 0
+#endif
+
+// gpio pin to power up the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
+#define CYW43_DEFAULT_PIN_WL_REG_ON 23u
+#endif
+
+// gpio pin for spi data out to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
+#define CYW43_DEFAULT_PIN_WL_DATA_OUT 24u
+#endif
+
+// gpio pin for spi data in from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
+#define CYW43_DEFAULT_PIN_WL_DATA_IN 24u
+#endif
+
+// gpio (irq) pin for the irq line from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
+#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 24u
+#endif
+
+// gpio pin for the spi clock line to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
+#define CYW43_DEFAULT_PIN_WL_CLOCK 29u
+#endif
+
+// gpio pin for the spi chip select to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CS
+#define CYW43_DEFAULT_PIN_WL_CS 25u
+#endif
+
+#endif
diff --git a/src/boards/include/boards/switchscience_picossci2_conta_base.h b/src/boards/include/boards/switchscience_picossci2_conta_base.h
index fcd7d85b2..638e47e57 100644
--- a/src/boards/include/boards/switchscience_picossci2_conta_base.h
+++ b/src/boards/include/boards/switchscience_picossci2_conta_base.h
@@ -17,7 +17,7 @@
#define _BOARDS_SWITCHSCIENCE_PICOSSCI2_CONTA_BASE_H
// For board detection
-#define SWITCHSCIENCE_PICOSSCI2_CONTA_BASE_H
+#define SWITCHSCIENCE_PICOSSCI2_CONTA_BASE
// --- RP2350 VARIANT ---
#define PICO_RP2350A 1
@@ -79,6 +79,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/switchscience_picossci2_dev_board.h b/src/boards/include/boards/switchscience_picossci2_dev_board.h
index 432d2d9b1..b674362bd 100644
--- a/src/boards/include/boards/switchscience_picossci2_dev_board.h
+++ b/src/boards/include/boards/switchscience_picossci2_dev_board.h
@@ -80,6 +80,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/switchscience_picossci2_micro.h b/src/boards/include/boards/switchscience_picossci2_micro.h
index 5d664997e..e1ccf359a 100644
--- a/src/boards/include/boards/switchscience_picossci2_micro.h
+++ b/src/boards/include/boards/switchscience_picossci2_micro.h
@@ -66,6 +66,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/switchscience_picossci2_rp2350_breakout.h b/src/boards/include/boards/switchscience_picossci2_rp2350_breakout.h
index 0ac128b13..ec53d1658 100644
--- a/src/boards/include/boards/switchscience_picossci2_rp2350_breakout.h
+++ b/src/boards/include/boards/switchscience_picossci2_rp2350_breakout.h
@@ -17,7 +17,7 @@
#define _BOARDS_SWITCHSCIENCE_PICOSSCI2_RP2350_BREAKOUT_H
// For board detection
-#define SWITCHSCIENCE_PICOSSCI2_RP2350_BREAKOUT_H
+#define SWITCHSCIENCE_PICOSSCI2_RP2350_BREAKOUT
// --- RP2350 VARIANT ---
#define PICO_RP2350A 1
@@ -79,6 +79,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/switchscience_picossci2_tiny.h b/src/boards/include/boards/switchscience_picossci2_tiny.h
index 48e3a9e83..f422017bd 100644
--- a/src/boards/include/boards/switchscience_picossci2_tiny.h
+++ b/src/boards/include/boards/switchscience_picossci2_tiny.h
@@ -17,7 +17,7 @@
#define _BOARDS_SWITCHSCIENCE_PICOSSCI2_TINY_H
// For board detection
-#define SWITCHSCIENCE_PICOSSCI2_TINY_H
+#define SWITCHSCIENCE_PICOSSCI2_TINY
// --- RP2350 VARIANT ---
#define PICO_RP2350A 1
@@ -79,6 +79,7 @@
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/boards/include/boards/tinycircuits_thumby_color_rp2350.h b/src/boards/include/boards/tinycircuits_thumby_color_rp2350.h
index 0a3c14a68..58088e581 100644
--- a/src/boards/include/boards/tinycircuits_thumby_color_rp2350.h
+++ b/src/boards/include/boards/tinycircuits_thumby_color_rp2350.h
@@ -93,6 +93,7 @@
#define PICO_VSYS_PIN 29
#endif
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
diff --git a/src/cmake/on_device.cmake b/src/cmake/on_device.cmake
index 3b2d8869a..5cabf3cc9 100644
--- a/src/cmake/on_device.cmake
+++ b/src/cmake/on_device.cmake
@@ -29,7 +29,8 @@ function(pico_add_dis_output TARGET)
pico_get_runtime_output_directory(${TARGET} output_path)
# PICO_CMAKE_CONFIG: PICO_NO_COPRO_DIS, Disable disassembly listing postprocessing that disassembles RP2350 coprocessor instructions, type=bool, default=0, group=build
- if (NOT (PICO_NO_COPRO_DIS OR PICO_NO_PICOTOOL))
+ if (NOT (PICO_NO_COPRO_DIS OR PICO_NO_PICOTOOL OR PICO_RISCV OR PICO_RP2040))
+ # Don't run coprocessor dissassembly on Risc-V or RP2040, as those don't have the RP2350 coprocessors
pico_init_picotool()
if(picotool_FOUND)
# add custom disassembly if we have picotool
@@ -40,7 +41,7 @@ function(pico_add_dis_output TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -h $ > ${output_path}$>,$,$>.dis
COMMAND ${CMAKE_OBJDUMP} -d $ >> ${output_path}$>,$,$>.dis
- ${EXTRA_COMMAND} || ${CMAKE_COMMAND} -E echo "WARNING: Disassembly is not correct"
+ ${EXTRA_COMMAND}
VERBATIM
)
endfunction()
@@ -63,7 +64,7 @@ function(pico_add_extra_outputs TARGET)
pico_add_map_output(${TARGET})
# PICO_CMAKE_CONFIG: PICO_NO_TARGET_NAME, Don't define PICO_TARGET_NAME, type=bool, default=0, group=build
- # PICO_BUILD_DEFINE: PICO_TARGET_NAME, The name of the build target being compiled (unless PICO_NO_TARGET_NAME set in build), type=string, default=target name, group=build
+ # PICO_BUILD_DEFINE: PICO_TARGET_NAME, Name of the build target being compiled (unless PICO_NO_TARGET_NAME set in build), type=string, default=target name, group=build
if (NOT PICO_NO_TARGET_NAME)
target_compile_definitions(${TARGET} PRIVATE
PICO_TARGET_NAME="${TARGET}"
@@ -94,4 +95,4 @@ set(PICO_NO_HARDWARE "0" CACHE INTERNAL "")
set(PICO_ON_DEVICE "1" CACHE INTERNAL "")
set(CMAKE_EXECUTABLE_SUFFIX .elf)
-set(CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
\ No newline at end of file
+set(CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
diff --git a/src/cmake/rp2_common.cmake b/src/cmake/rp2_common.cmake
index 494b1202b..726bab933 100644
--- a/src/cmake/rp2_common.cmake
+++ b/src/cmake/rp2_common.cmake
@@ -60,6 +60,7 @@ pico_add_subdirectory(rp2_common/hardware_timer)
pico_add_subdirectory(rp2_common/hardware_uart)
pico_add_subdirectory(rp2_common/hardware_vreg)
pico_add_subdirectory(rp2_common/hardware_watchdog)
+pico_add_subdirectory(rp2_common/hardware_xip_cache)
pico_add_subdirectory(rp2_common/hardware_xosc)
if (PICO_RP2350 OR PICO_COMBINED_DOCS)
@@ -79,9 +80,8 @@ if (PICO_RISCV OR PICO_COMBINED_DOCS)
pico_add_subdirectory(rp2_common/hardware_hazard3)
endif()
-# Helper functions to connect to data/functions in the bootrom
-pico_add_subdirectory(rp2_common/pico_bootrom)
-
+# Basic bootrom headers
+pico_add_subdirectory(rp2_common/boot_bootrom_headers)
pico_add_subdirectory(rp2_common/pico_platform_compiler)
pico_add_subdirectory(rp2_common/pico_platform_sections)
pico_add_subdirectory(rp2_common/pico_platform_panic)
@@ -89,6 +89,8 @@ pico_add_subdirectory(rp2_common/pico_platform_panic)
if (NOT PICO_BARE_METAL)
# NOTE THE ORDERING HERE IS IMPORTANT AS SOME TARGETS CHECK ON EXISTENCE OF OTHER TARGETS
pico_add_subdirectory(rp2_common/pico_aon_timer)
+ # Helper functions to connect to data/functions in the bootrom
+ pico_add_subdirectory(rp2_common/pico_bootrom)
pico_add_subdirectory(rp2_common/pico_bootsel_via_double_reset)
pico_add_subdirectory(rp2_common/pico_multicore)
pico_add_subdirectory(rp2_common/pico_unique_id)
diff --git a/src/common/boot_picobin_headers/include/boot/picobin.h b/src/common/boot_picobin_headers/include/boot/picobin.h
index 44ce9909a..25308478b 100644
--- a/src/common/boot_picobin_headers/include/boot/picobin.h
+++ b/src/common/boot_picobin_headers/include/boot/picobin.h
@@ -11,9 +11,13 @@
#include "pico/platform.h"
#else
#ifndef _u
+#ifdef __ASSEMBLER__
+#define _u(x) x
+#else
#define _u(x) x ## u
#endif
#endif
+#endif
/** \file picobin.h
* \defgroup boot_picobin_headers boot_picobin_headers
@@ -48,6 +52,7 @@
// ----
+#define _PICOBIN_INDEX_TO_BITS(y, x) (y ## x << y ## _LSB)
#define PICOBIN_INDEX_TO_BITS(y, x) (y ## _ ## x << y ## _LSB)
#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_LSB _u(0)
@@ -55,27 +60,27 @@
#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_INVALID _u(0x0)
#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_EXE _u(0x1)
#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_DATA _u(0x2)
-#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_AS_BITS(x) PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_IMAGE_TYPE, x)
+#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_AS_BITS(x) _PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_IMAGE_TYPE, _ ## x)
#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_LSB _u(4)
#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_BITS _u(0x0030)
#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_UNSPECIFIED _u(0x0)
#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_NS _u(0x1)
#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_S _u(0x2)
-#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_AS_BITS(x) PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_EXE_SECURITY, x)
+#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_AS_BITS(x) _PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_EXE_SECURITY, _ ## x)
#define PICOBIN_IMAGE_TYPE_EXE_CPU_LSB _u(8)
#define PICOBIN_IMAGE_TYPE_EXE_CPU_BITS _u(0x0700)
#define PICOBIN_IMAGE_TYPE_EXE_CPU_ARM _u(0)
#define PICOBIN_IMAGE_TYPE_EXE_CPU_RISCV _u(1)
#define PICOBIN_IMAGE_TYPE_EXE_CPU_VARMULET _u(2)
-#define PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(x) PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_EXE_CPU, x)
+#define PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(x) _PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_EXE_CPU, _ ## x)
#define PICOBIN_IMAGE_TYPE_EXE_CHIP_LSB _u(12)
#define PICOBIN_IMAGE_TYPE_EXE_CHIP_BITS _u(0x7000)
#define PICOBIN_IMAGE_TYPE_EXE_CHIP_RP2040 _u(0)
#define PICOBIN_IMAGE_TYPE_EXE_CHIP_RP2350 _u(1)
-#define PICOBIN_IMAGE_TYPE_EXE_CHIP_AS_BITS(x) PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_EXE_CHIP, x)
+#define PICOBIN_IMAGE_TYPE_EXE_CHIP_AS_BITS(x) _PICOBIN_INDEX_TO_BITS(PICOBIN_IMAGE_TYPE_EXE_CHIP, _ ## x)
#define PICOBIN_IMAGE_TYPE_EXE_TBYB_BITS _u(0x8000)
@@ -131,7 +136,7 @@
#define PICOBIN_PARTITION_FLAGS_LINK_TYPE_NONE _u(0)
#define PICOBIN_PARTITION_FLAGS_LINK_TYPE_A_PARTITION _u(1)
#define PICOBIN_PARTITION_FLAGS_LINK_TYPE_OWNER_PARTITION _u(2)
-#define PICOBIN_PARTITION_FLAGS_LINK_TYPE_AS_BITS(x) PICOBIN_INDEX_TO_BITS(PICOBIN_PARTITION_FLAGS_LINK_TYPE, x)
+#define PICOBIN_PARTITION_FLAGS_LINK_TYPE_AS_BITS(x) _PICOBIN_INDEX_TO_BITS(PICOBIN_PARTITION_FLAGS_LINK_TYPE, _ ## x)
#define PICOBIN_HASH_SHA256 _u(0x01)
diff --git a/src/common/boot_picoboot_headers/BUILD.bazel b/src/common/boot_picoboot_headers/BUILD.bazel
index ec09b7d44..7be4b9580 100644
--- a/src/common/boot_picoboot_headers/BUILD.bazel
+++ b/src/common/boot_picoboot_headers/BUILD.bazel
@@ -1,5 +1,7 @@
package(default_visibility = ["//visibility:public"])
+# This needs to remain compatible with the host build since it's used by
+# Picotool.
cc_library(
name = "boot_picoboot_headers",
hdrs = [
diff --git a/src/common/boot_picoboot_headers/include/boot/picoboot_constants.h b/src/common/boot_picoboot_headers/include/boot/picoboot_constants.h
index ac78ea213..ffb3b8cc4 100644
--- a/src/common/boot_picoboot_headers/include/boot/picoboot_constants.h
+++ b/src/common/boot_picoboot_headers/include/boot/picoboot_constants.h
@@ -9,11 +9,11 @@
#define REBOOT2_TYPE_MASK 0x0f
-// note these match REBOOT_TYPE in pico/bootrom_constants.h (also 0 is used for PC_SP for backwards compatibility with RP2040)
+// note these match REBOOT_TYPE in pico/bootrom_constants.h
// values 0-7 are secure/non-secure
#define REBOOT2_FLAG_REBOOT_TYPE_NORMAL 0x0 // param0 = diagnostic partition
-#define REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL 0x2 // param0 = bootsel_flags, param1 = gpio_config
-#define REBOOT2_FLAG_REBOOT_TYPE_RAM_IMAGE 0x3 // param0 = image_base, param1 = image_end
+#define REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL 0x2 // param0 = gpio_pin_number, param1 = flags
+#define REBOOT2_FLAG_REBOOT_TYPE_RAM_IMAGE 0x3 // param0 = image_region_base, param1 = image_region_size
#define REBOOT2_FLAG_REBOOT_TYPE_FLASH_UPDATE 0x4 // param0 = update_base
// values 8-15 are secure only
@@ -39,4 +39,4 @@
#define UF2_STATUS_ABORT_BAD_ADDRESS 0x20
#define UF2_STATUS_ABORT_WRITE_ERROR 0x40
#define UF2_STATUS_ABORT_REBOOT_FAILED 0x80
-#endif
\ No newline at end of file
+#endif
diff --git a/src/common/boot_uf2_headers/include/boot/uf2.h b/src/common/boot_uf2_headers/include/boot/uf2.h
index 271540a20..ffdcb90d1 100644
--- a/src/common/boot_uf2_headers/include/boot/uf2.h
+++ b/src/common/boot_uf2_headers/include/boot/uf2.h
@@ -20,10 +20,11 @@
#define UF2_MAGIC_START1 0x9E5D5157u
#define UF2_MAGIC_END 0x0AB16F30u
-#define UF2_FLAG_NOT_MAIN_FLASH 0x00000001u
-#define UF2_FLAG_FILE_CONTAINER 0x00001000u
-#define UF2_FLAG_FAMILY_ID_PRESENT 0x00002000u
-#define UF2_FLAG_MD5_PRESENT 0x00004000u
+#define UF2_FLAG_NOT_MAIN_FLASH 0x00000001u
+#define UF2_FLAG_FILE_CONTAINER 0x00001000u
+#define UF2_FLAG_FAMILY_ID_PRESENT 0x00002000u
+#define UF2_FLAG_MD5_PRESENT 0x00004000u
+#define UF2_FLAG_EXTENSION_FLAGS_PRESENT 0x00008000u
#define RP2040_FAMILY_ID 0xe48bff56u
#define ABSOLUTE_FAMILY_ID 0xe48bff57u
@@ -33,6 +34,8 @@
#define RP2350_ARM_NS_FAMILY_ID 0xe48bff5bu
#define FAMILY_ID_MAX 0xe48bff5bu
+// 04 e3 57 99
+#define UF2_EXTENSION_RP2_IGNORE_BLOCK 0x9957e304
struct uf2_block {
// 32 byte header
diff --git a/src/common/pico_base_headers/CMakeLists.txt b/src/common/pico_base_headers/CMakeLists.txt
index 57973fea7..89f89b501 100644
--- a/src/common/pico_base_headers/CMakeLists.txt
+++ b/src/common/pico_base_headers/CMakeLists.txt
@@ -6,6 +6,11 @@ if (NOT TARGET pico_base_headers)
target_compile_definitions(pico_base_headers INTERFACE
PICO_BOARD="${PICO_BOARD}")
+ foreach(override ${PICO_BOARD_CMAKE_OVERRIDES})
+ target_compile_definitions(pico_base_headers INTERFACE
+ ${override}=${${override}})
+ endforeach()
+
target_link_libraries(pico_base_headers INTERFACE pico_platform_headers)
list(APPEND PICO_SDK_POST_LIST_FILES ${CMAKE_CURRENT_LIST_DIR}/generate_config_header.cmake)
diff --git a/src/common/pico_binary_info/include/pico/binary_info/code.h b/src/common/pico_binary_info/include/pico/binary_info/code.h
index bc2126f5f..63239a963 100644
--- a/src/common/pico_binary_info/include/pico/binary_info/code.h
+++ b/src/common/pico_binary_info/include/pico/binary_info/code.h
@@ -208,8 +208,62 @@ static const struct _binary_info_named_group __bi_lineno_var_name = { \
#define bi_7pins_with_func(p0, p1, p2, p3, p4, p5, p6,func) __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p2) << 24) | ((uint64_t)(p3) << 32) | ((uint64_t)(p4) << 40) | ((uint64_t)(p5) << 48) | ((uint64_t)(p6) << 56))
#define bi_1pin_with_name(p0, name) bi_pin_mask_with_name(1ull << (p0), name)
-#define bi_2pins_with_names(p0, name0, p1, name1) bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)), name0 "|" name1)
-#define bi_3pins_with_names(p0, name0, p1, name1, p2, name2) bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)) | (1ull << (p2)), name0 "|" name1 "|" name2)
-#define bi_4pins_with_names(p0, name0, p1, name1, p2, name2, p3, name3) bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)) | (1ull << (p2)) | (1ull << (p3)), name0 "|" name1 "|" name2 "|" name3)
+#define bi_2pins_with_names(p0, name0, p1, name1) bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)), p0 < p1 ? name0 "|" name1 : name1 "|" name0)
+#define bi_3pins_with_names(p0, name0, p1, name1, p2, name2) bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)) | (1ull << (p2)),\
+ p0 < p1 ?\
+ (p1 < p2 ?\
+ name0 "|" name1 "|" name2:\
+ (p0 < p2 ? name0 "|" name2 "|" name1 : name2 "|" name0 "|" name1)):\
+ (p1 < p2 ?\
+ (p0 < p2 ? name1 "|" name0 "|" name2 : name1 "|" name2 "|" name0) :\
+ name2 "|" name1 "|" name0))
+#define bi_4pins_with_names(p0, name0, p1, name1, p2, name2, p3, name3) bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)) | (1ull << (p2)) | (1ull << (p3)),\
+ p0 < p1 ?\
+ (p1 < p2 ?\
+ (p2 < p3 ?\
+ name0 "|" name1 "|" name2 "|" name3:\
+ (p0 < p3 ?\
+ (p1 < p3 ?\
+ name0 "|" name1 "|" name3 "|" name2:\
+ name0 "|" name3 "|" name1 "|" name2):\
+ name3 "|" name0 "|" name1 "|" name2)):\
+ (p2 < p3 ?\
+ (p0 < p2 ?\
+ (p1 < p3 ?\
+ name0 "|" name2 "|" name1 "|" name3:\
+ name0 "|" name2 "|" name3 "|" name1):\
+ (p0 < p3 ?\
+ (p1 < p3 ?\
+ name2 "|" name0 "|" name1 "|" name3:\
+ name2 "|" name0 "|" name3 "|" name1):\
+ name2 "|" name3 "|" name0 "|" name1)):\
+ (p0 < p2 ?\
+ (p0 < p3 ?\
+ name0 "|" name3 "|" name2 "|" name1:\
+ name3 "|" name0 "|" name2 "|" name1):\
+ name3 "|" name2 "|" name0 "|" name1))):\
+ (p1 < p2 ?\
+ (p2 < p3 ?\
+ (p0 < p2 ?\
+ name1 "|" name0 "|" name2 "|" name3:\
+ (p0 < p3 ?\
+ name1 "|" name2 "|" name0 "|" name3:\
+ name1 "|" name2 "|" name3 "|" name0)):\
+ (p0 < p2 ?\
+ (p0 < p3 ?\
+ name1 "|" name0 "|" name3 "|" name2:\
+ (p1 < p3 ?\
+ name1 "|" name3 "|" name0 "|" name2:\
+ name3 "|" name1 "|" name0 "|" name2)):\
+ (p1 < p3 ?\
+ name1 "|" name3 "|" name2 "|" name0:\
+ name3 "|" name1 "|" name2 "|" name0))):\
+ (p2 < p3 ?\
+ (p0 < p3 ?\
+ name2 "|" name1 "|" name0 "|" name3:\
+ (p1 < p3 ?\
+ name2 "|" name1 "|" name3 "|" name0:\
+ name2 "|" name3 "|" name1 "|" name0)):\
+ name3 "|" name2 "|" name1 "|" name0)))
#endif
diff --git a/src/common/pico_stdlib_headers/include/pico/stdlib.h b/src/common/pico_stdlib_headers/include/pico/stdlib.h
index 811f565c9..5ebad89aa 100644
--- a/src/common/pico_stdlib_headers/include/pico/stdlib.h
+++ b/src/common/pico_stdlib_headers/include/pico/stdlib.h
@@ -57,15 +57,15 @@ extern "C" {
#include "pico/stdio_semihosting.h"
#endif
-// PICO_CONFIG: PICO_DEFAULT_LED_PIN, Optionally define a pin that drives a regular LED on the board, default=Usually provided via board header, group=pico_stdlib
+// PICO_CONFIG: PICO_DEFAULT_LED_PIN, Optionally define a pin that drives a regular LED on the board, default=Usually provided via board header, type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_stdlib
// PICO_CONFIG: PICO_DEFAULT_LED_PIN_INVERTED, 1 if LED is inverted or 0 if not, type=int, default=0, group=pico_stdlib
#ifndef PICO_DEFAULT_LED_PIN_INVERTED
#define PICO_DEFAULT_LED_PIN_INVERTED 0
#endif
-// PICO_CONFIG: PICO_DEFAULT_WS2812_PIN, Optionally define a pin that controls data to a WS2812 compatible LED on the board, group=pico_stdlib
-// PICO_CONFIG: PICO_DEFAULT_WS2812_POWER_PIN, Optionally define a pin that controls power to a WS2812 compatible LED on the board, group=pico_stdlib
+// PICO_CONFIG: PICO_DEFAULT_WS2812_PIN, Optionally define a pin that controls data to a WS2812 compatible LED on the board, type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_stdlib
+// PICO_CONFIG: PICO_DEFAULT_WS2812_POWER_PIN, Optionally define a pin that controls power to a WS2812 compatible LED on the board, type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_stdlib
/*! \brief Set up the default UART and assign it to the default GPIOs
* \ingroup pico_stdlib
diff --git a/src/common/pico_time/include/pico/time.h b/src/common/pico_time/include/pico/time.h
index 699523e9e..53a606bcb 100644
--- a/src/common/pico_time/include/pico/time.h
+++ b/src/common/pico_time/include/pico/time.h
@@ -284,6 +284,8 @@ void sleep_ms(uint32_t ms);
* return false; // timed out
* }
* ```
+ * NOTE: This method should always be used in a loop associated with checking another "event" variable, since
+ * processor events are a shared resource and can happen for a large number of reasons.
*
* @param timeout_timestamp the timeout time
* @return true if the target time is reached, false otherwise
@@ -584,7 +586,7 @@ int64_t alarm_pool_remaining_alarm_time_us(alarm_pool_t *pool, alarm_id_t alarm_
* @param pool the alarm_pool containing the alarm
* @param alarm_id the alarm
*
- * @return >=0 the number of microseconds before the next trigger (INT32_MAX if the number of ms is higher than can be represented0
+ * @return >=0 the number of milliseconds before the next trigger (INT32_MAX if the number of ms is higher than can be represented0
* @return <0 if either the given alarm is not in progress or it has passed
*/
int32_t alarm_pool_remaining_alarm_time_ms(alarm_pool_t *pool, alarm_id_t alarm_id);
@@ -700,7 +702,7 @@ int64_t remaining_alarm_time_us(alarm_id_t alarm_id);
*
* @param alarm_id the alarm
*
- * @return >=0 the number of microseconds before the next trigger (INT32_MAX if the number of ms is higher than can be represented0
+ * @return >=0 the number of milliseconds before the next trigger (INT32_MAX if the number of ms is higher than can be represented0
* @return <0 if either the given alarm is not in progress or it has passed
*/
int32_t remaining_alarm_time_ms(alarm_id_t alarm_id);
diff --git a/src/common/pico_time/time.c b/src/common/pico_time/time.c
index 118547d8a..78ad26f07 100644
--- a/src/common/pico_time/time.c
+++ b/src/common/pico_time/time.c
@@ -136,13 +136,14 @@ static void alarm_pool_irq_handler(void);
static void alarm_pool_irq_handler(void) {
// This IRQ handler does the main work, as it always (assuming the IRQ hasn't been enabled on both cores
// which is unsupported) run on the alarm pool's core, and can't be preempted by itself, meaning
- // that it doesn't need locks except to protect against linked list access
+ // that it doesn't need locks except to protect against linked list, or other state access.
+ // This simplifies the code considerably, and makes it much faster in general, even though we are forced to take
+ // two IRQs per alarm.
uint timer_alarm_num;
alarm_pool_timer_t *timer = ta_from_current_irq(&timer_alarm_num);
uint timer_num = ta_timer_num(timer);
alarm_pool_t *pool = pools[timer_num][timer_alarm_num];
assert(pool->timer_alarm_num == timer_alarm_num);
- int64_t now = (int64_t) ta_time_us_64(timer);
int64_t earliest_target;
// 1. clear force bits if we were forced (do this outside the loop, as forcing is hopefully rare)
ta_clear_force_irq(timer, timer_alarm_num);
@@ -159,7 +160,7 @@ static void alarm_pool_irq_handler(void) {
if (earliest_index >= 0) {
alarm_pool_entry_t *earliest_entry = &pool->entries[earliest_index];
earliest_target = earliest_entry->target;
- if ((now - earliest_target) >= 0) {
+ if (((int64_t)ta_time_us_64(timer) - earliest_target) >= 0) {
// time to call the callback now (or in the past)
// note that an entry->target of < 0 means the entry has been canceled (not this is set
// by this function, in response to the entry having been queued by the cancel_alarm API
@@ -259,15 +260,22 @@ static void alarm_pool_irq_handler(void) {
index = next;
}
}
- now = (int64_t) ta_time_us_64(timer);
earliest_index = pool->ordered_head;
if (earliest_index < 0) break;
// need to wait
alarm_pool_entry_t *earliest_entry = &pool->entries[earliest_index];
earliest_target = earliest_entry->target;
- ta_set_timeout(timer, timer_alarm_num, earliest_target);
- // check we haven't now past the target time; if not we don't want to loop again
- } while ((earliest_target - now) <= 0);
+ // we are leaving a timeout every 2^32 microseconds anyway if there is no valid target, so we can choose any value.
+ // best_effort_wfe_or_timeout now relies on it being the last value set, and arguably this is the
+ // best value anyway, as it is the furthest away from the last fire.
+ if (earliest_target != -1) { // cancelled alarm has target of -1
+ ta_set_timeout(timer, timer_alarm_num, earliest_target);
+ }
+ // check we haven't now passed the target time; if not we don't want to loop again
+ } while ((earliest_target - (int64_t)ta_time_us_64(timer)) <= 0);
+ // We always want the timer IRQ to wake a WFE so that best_effort_wfe_or_timeout() will wake up. It will wake
+ // a WFE on its own core by nature of having taken an IRQ, but we do an explicit SEV so it wakes the other core
+ __sev();
}
void alarm_pool_post_alloc_init(alarm_pool_t *pool, alarm_pool_timer_t *timer, uint hardware_alarm_num, uint max_timers) {
@@ -439,26 +447,48 @@ bool best_effort_wfe_or_timeout(absolute_time_t timeout_timestamp) {
return time_reached(timeout_timestamp);
} else {
alarm_id_t id;
- id = add_alarm_at(timeout_timestamp, sleep_until_callback, NULL, false);
- if (id <= 0) {
- tight_loop_contents();
+ // note that as of SDK 2.0.0 calling add_alarm_at always causes a SEV. What we really
+ // want to do is cause an IRQ at the specified time in the future if there is not
+ // an IRQ already happening before then. The problem is that the IRQ may be happening on the
+ // other core, so taking an IRQ is the only way to get the state protection.
+ //
+ // Therefore, we make a compromise; we will set the alarm, if we won't wake up before the right time
+ // already. This means that repeated calls to this function with the same timeout will work correctly
+ // after the first one! This is fine, because we ask callers to use a polling loop on another
+ // event variable when using this function.
+ //
+ // For this to work, we require that once we have set an alarm, an SEV happens no later than that, even
+ // if we cancel the alarm as we do below. Therefore, the IRQ handler (which is always enabled) will
+ // never set its wakeup time to a later value, but instead wake up once and then wake up again.
+ //
+ // This overhead when canceling alarms is a small price to pay for the much simpler/faster/cleaner
+ // implementation that relies on the IRQ handler (on a single core) being the only state accessor.
+ //
+ // Note also, that the use of software spin locks on RP2350 to access state would always cause a SEV
+ // due to use of LDREX etc., so actually using spin locks to protect the state would be worse.
+ if (ta_wakes_up_on_or_before(alarm_pool_get_default()->timer, alarm_pool_get_default()->timer_alarm_num,
+ (int64_t)to_us_since_boot(timeout_timestamp))) {
+ // we already are waking up at or before when we want to (possibly due to us having been called
+ // before in a loop), so we can do an actual WFE. Note we rely on the fact that the alarm pool IRQ
+ // handler always does an explicit SEV, since it may be on the other core.
+ __wfe();
return time_reached(timeout_timestamp);
} else {
- // the above alarm add now may force an IRQ which will wake us up,
- // so we want to consume one __wfe.. we do an explicit __sev
- // just to make sure there is one
- __sev(); // make sure there is an event sow ee don't block
- __wfe();
- if (!time_reached(timeout_timestamp))
- {
- // ^ at the point above the timer hadn't fired, so it is safe
- // to wait; the event will happen due to IRQ at some point between
- // then and the correct wakeup time
- __wfe();
+ id = add_alarm_at(timeout_timestamp, sleep_until_callback, NULL, false);
+ if (id <= 0) {
+ tight_loop_contents();
+ return time_reached(timeout_timestamp);
+ } else {
+ if (!time_reached(timeout_timestamp)) {
+ // ^ at the point above the timer hadn't fired, so it is safe
+ // to wait; the event will happen due to IRQ at some point between
+ // then and the correct wakeup time
+ __wfe();
+ }
+ // we need to clean up if it wasn't us that caused the wfe; if it was this will be a noop.
+ cancel_alarm(id);
+ return time_reached(timeout_timestamp);
}
- // we need to clean up if it wasn't us that caused the wfe; if it was this will be a noop.
- cancel_alarm(id);
- return time_reached(timeout_timestamp);
}
}
#else
diff --git a/src/common/pico_util/datetime.c b/src/common/pico_util/datetime.c
index c113ce466..130e2d5a6 100644
--- a/src/common/pico_util/datetime.c
+++ b/src/common/pico_util/datetime.c
@@ -1,8 +1,23 @@
#include "pico/util/datetime.h"
-#include
+#if !PICO_ON_DEVICE && __APPLE__
+// if we're compiling with LLVM on Apple, __weak does something else, but we don't care about overriding these anyway on host builds
+#define __datetime_weak
+#else
+#define __datetime_weak __weak
+#endif
+
+__datetime_weak struct tm * pico_localtime_r(const time_t *time, struct tm *tm) {
+ return localtime_r(time, tm);
+}
+
+__datetime_weak time_t pico_mktime(struct tm *tm) {
+ return mktime(tm);
+}
#if PICO_INCLUDE_RTC_DATETIME
+#include
+
static const char *DATETIME_MONTHS[12] = {
"January",
"February",
@@ -41,17 +56,29 @@ void datetime_to_str(char *buf, uint buf_size, const datetime_t *t) {
t->year);
};
+void datetime_to_tm(const datetime_t *dt, struct tm *tm) {
+ tm->tm_year = dt->year - 1900;
+ tm->tm_mon = dt->month - 1;
+ tm->tm_mday = dt->day;
+ tm->tm_hour = dt->hour;
+ tm->tm_min = dt->min;
+ tm->tm_sec = dt->sec;
+}
+
+void tm_to_datetime(const struct tm *tm, datetime_t *dt) {
+ dt->year = (int16_t) (tm->tm_year + 1900); // 0..4095
+ dt->month = (int8_t) (tm->tm_mon + 1); // 1..12, 1 is January
+ dt->day = (int8_t) tm->tm_mday; // 1..28,29,30,31 depending on month
+ dt->dotw = (int8_t) tm->tm_wday; // 0..6, 0 is Sunday
+ dt->hour = (int8_t) tm->tm_hour; // 0..23
+ dt->min = (int8_t) tm->tm_min; // 0..59
+ dt->sec = (int8_t) tm->tm_sec; // 0..59
+}
bool time_to_datetime(time_t time, datetime_t *dt) {
struct tm local;
- if (localtime_r(&time, &local)) {
- dt->year = (int16_t) (local.tm_year + 1900); // 0..4095
- dt->month = (int8_t) (local.tm_mon + 1); // 1..12, 1 is January
- dt->day = (int8_t) local.tm_mday; // 1..28,29,30,31 depending on month
- dt->dotw = (int8_t) local.tm_wday; // 0..6, 0 is Sunday
- dt->hour = (int8_t) local.tm_hour; // 0..23
- dt->min = (int8_t) local.tm_min; // 0..59
- dt->sec = (int8_t) local.tm_sec; // 0..59
+ if (pico_localtime_r(&time, &local)) {
+ tm_to_datetime(&local, dt);
return true;
}
return false;
@@ -59,13 +86,8 @@ bool time_to_datetime(time_t time, datetime_t *dt) {
bool datetime_to_time(const datetime_t *dt, time_t *time) {
struct tm local;
- local.tm_year = dt->year - 1900;
- local.tm_mon = dt->month - 1;
- local.tm_mday = dt->day;
- local.tm_hour = dt->hour;
- local.tm_min = dt->min;
- local.tm_sec = dt->sec;
- *time = mktime(&local);
+ datetime_to_tm(dt, &local);
+ *time = pico_mktime(&local);
return *time >= 0;
}
diff --git a/src/common/pico_util/include/pico/util/datetime.h b/src/common/pico_util/include/pico/util/datetime.h
index 92e6d6460..05dea5633 100644
--- a/src/common/pico_util/include/pico/util/datetime.h
+++ b/src/common/pico_util/include/pico/util/datetime.h
@@ -19,8 +19,10 @@ extern "C" {
* \ingroup pico_util
*/
-#if PICO_INCLUDE_RTC_DATETIME
#include
+#include
+
+#if PICO_INCLUDE_RTC_DATETIME
/*! \brief Convert a datetime_t structure to a string
* \ingroup util_datetime
@@ -33,14 +35,33 @@ void datetime_to_str(char *buf, uint buf_size, const datetime_t *t);
bool time_to_datetime(time_t time, datetime_t *dt);
bool datetime_to_time(const datetime_t *dt, time_t *time);
+
+void datetime_to_tm(const datetime_t *dt, struct tm *tm);
+void tm_to_datetime(const struct tm *tm, datetime_t *dt);
+
#endif
-#include
uint64_t timespec_to_ms(const struct timespec *ts);
uint64_t timespec_to_us(const struct timespec *ts);
void ms_to_timespec(uint64_t ms, struct timespec *ts);
void us_to_timespec(uint64_t ms, struct timespec *ts);
+/*! \brief localtime_r implementation for use by the pico_util datetime functions
+ * \ingroup util_datetime
+ *
+ * This method calls localtime_r from the C library by default,
+ * but is declared as a weak implementation to allow user code to override it
+ */
+struct tm *pico_localtime_r(const time_t *time, struct tm *tm);
+
+/*! \brief mktime implementation for use by the pico_util datetime functions
+* \ingroup util_datetime
+*
+* This method calls mktime from the C library by default,
+* but is declared as a weak implementation to allow user code to override it
+*/
+time_t pico_mktime(struct tm *tm);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/pico_util/include/pico/util/pheap.h b/src/common/pico_util/include/pico/util/pheap.h
index d51804cdf..402d9cb3a 100644
--- a/src/common/pico_util/include/pico/util/pheap.h
+++ b/src/common/pico_util/include/pico/util/pheap.h
@@ -54,6 +54,7 @@ typedef struct pheap_node {
/**
* \brief A user comparator function for nodes in a pairing heap.
+ * \ingroup util_pheap
*
* \return true if a < b in natural order. Note this relative ordering must be stable from call to call.
*/
@@ -75,6 +76,7 @@ typedef struct pheap {
* of nodes. The heap itself stores no user per-node state, it is expected
* that the user maintains a companion array. A comparator function must
* be provided so that the heap implementation can determine the relative ordering of nodes
+ * \ingroup util_pheap
*
* \param max_nodes the maximum number of nodes that may be in the heap (this is bounded by
* PICO_PHEAP_MAX_ENTRIES which defaults to 255 to be able to store indexes
@@ -87,12 +89,14 @@ pheap_t *ph_create(uint max_nodes, pheap_comparator comparator, void *user_data)
/**
* \brief Removes all nodes from the pairing heap
+ * \ingroup util_pheap
* \param heap the heap
*/
void ph_clear(pheap_t *heap);
/**
* \brief De-allocates a pairing heap
+ * \ingroup util_pheap
*
* Note this method must *ONLY* be called on heaps created by ph_create()
* \param heap the heap
@@ -136,6 +140,7 @@ static pheap_node_id_t ph_merge_nodes(pheap_t *heap, pheap_node_id_t a, pheap_no
/**
* \brief Allocate a new node from the unused space in the heap
+ * \ingroup util_pheap
*
* \param heap the heap
* \return an identifier for the node, or 0 if the heap is full
@@ -152,6 +157,7 @@ static inline pheap_node_id_t ph_new_node(pheap_t *heap) {
/**
* \brief Inserts a node into the heap.
+ * \ingroup util_pheap
*
* This method inserts a node (previously allocated by ph_new_node())
* into the heap, determining the correct order by calling
@@ -172,6 +178,7 @@ static inline pheap_node_id_t ph_insert_node(pheap_t *heap, pheap_node_id_t id)
/**
* \brief Returns the head node in the heap, i.e. the node
* which compares first, but without removing it from the heap.
+ * \ingroup util_pheap
*
* \param heap the heap
* \return the current head node id
@@ -184,6 +191,7 @@ static inline pheap_node_id_t ph_peek_head(pheap_t *heap) {
* \brief Remove the head node from the pairing heap. This head node is
* the node which compares first in the logical ordering provided
* by the comparator.
+ * \ingroup util_pheap
*
* Note that in the case of free == true, the returned id is no longer
* allocated and may be re-used by future node allocations, so the caller
@@ -201,6 +209,7 @@ pheap_node_id_t ph_remove_head(pheap_t *heap, bool free);
* \brief Remove the head node from the pairing heap. This head node is
* the node which compares first in the logical ordering provided
* by the comparator.
+ * \ingroup util_pheap
*
* Note that the returned id will be freed, and thus may be re-used by future node allocations,
* so the caller should retrieve any per node state from the companion array before modifying
@@ -216,6 +225,7 @@ static inline pheap_node_id_t ph_remove_and_free_head(pheap_t *heap) {
/**
* \brief Remove and free an arbitrary node from the pairing heap. This is a more
* costly operation than removing the head via ph_remove_and_free_head()
+ * \ingroup util_pheap
*
* @param heap the heap
* @param id the id of the node to free
@@ -226,6 +236,7 @@ bool ph_remove_and_free_node(pheap_t *heap, pheap_node_id_t id);
/**
* \brief Determine if the heap contains a given node. Note containment refers
* to whether the node is inserted (ph_insert_node()) vs allocated (ph_new_node())
+ * \ingroup util_pheap
*
* @param heap the heap
* @param id the id of the node
@@ -238,6 +249,7 @@ static inline bool ph_contains_node(pheap_t *heap, pheap_node_id_t id) {
/**
* \brief Free a node that is not currently in the heap, but has been allocated
+ * \ingroup util_pheap
*
* @param heap the heap
* @param id the id of the node
@@ -256,6 +268,7 @@ static inline void ph_free_node(pheap_t *heap, pheap_node_id_t id) {
/**
* \brief Print a representation of the heap for debugging
+ * \ingroup util_pheap
*
* @param heap the heap
* @param dump_key a method to print a node value
@@ -266,6 +279,7 @@ void ph_dump(pheap_t *heap, void (*dump_key)(pheap_node_id_t id, void *user_data
/**
* \brief Initialize a statically allocated heap (ph_create() using the C heap).
* The heap member `nodes` must be allocated of size max_nodes.
+ * \ingroup util_pheap
*
* @param heap the heap
* @param max_nodes the max number of nodes in the heap (matching the size of the heap's nodes array)
@@ -277,6 +291,7 @@ void ph_post_alloc_init(pheap_t *heap, uint max_nodes, pheap_comparator comparat
/**
* \brief Define a statically allocated pairing heap. This must be initialized
* by ph_post_alloc_init
+ * \ingroup util_pheap
*/
#define PHEAP_DEFINE_STATIC(name, _max_nodes) \
static_assert(_max_nodes && _max_nodes < (1u << (8 * sizeof(pheap_node_id_t))), ""); \
diff --git a/src/host/hardware_irq/include/hardware/irq.h b/src/host/hardware_irq/include/hardware/irq.h
index 83c3a8487..0e881b7a7 100644
--- a/src/host/hardware_irq/include/hardware/irq.h
+++ b/src/host/hardware_irq/include/hardware/irq.h
@@ -18,7 +18,7 @@
#define PICO_DISABLE_SHARED_IRQ_HANDLERS 0
#endif
-// PICO_CONFIG: PICO_VTABLE_PER_CORE, user is using separate vector tables per core, type=bool, default=0, group=hardware_irq
+// PICO_CONFIG: PICO_VTABLE_PER_CORE, User is using separate vector tables per core, type=bool, default=0, group=hardware_irq
#ifndef PICO_VTABLE_PER_CORE
#define PICO_VTABLE_PER_CORE 0
#endif
diff --git a/src/host/hardware_sync/include/hardware/sync.h b/src/host/hardware_sync/include/hardware/sync.h
index f31c21630..ffbc08032 100644
--- a/src/host/hardware_sync/include/hardware/sync.h
+++ b/src/host/hardware_sync/include/hardware/sync.h
@@ -26,52 +26,52 @@ static inline void atomic_thread_fence(uint x) {}
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_ATOMIC, Spinlock ID for atomic protection, min=0, max=31, default=8, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_ATOMIC, Spinlock ID for atomics, min=0, max=31, default=8, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_ATOMIC
#define PICO_SPINLOCK_ID_ATOMIC 8
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_IRQ, Spinlock ID for IRQ protection, min=0, max=31, default=9, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_IRQ, Spinlock ID for IRQ protection, min=0, max=31, default=9, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_IRQ
#define PICO_SPINLOCK_ID_IRQ 9
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_TIMER, Spinlock ID for Timer protection, min=0, max=31, default=10, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_TIMER, Spinlock ID for Timer protection, min=0, max=31, default=10, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_TIMER
#define PICO_SPINLOCK_ID_TIMER 10
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_HARDWARE_CLAIM, Spinlock ID for Hardware claim protection, min=0, max=31, default=11, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_HARDWARE_CLAIM, Spinlock ID for Hardware claim protection, min=0, max=31, default=11, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_HARDWARE_CLAIM
#define PICO_SPINLOCK_ID_HARDWARE_CLAIM 11
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_RAND, Spinlock ID for Random Number Generator, min=0, max=31, default=12, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_RAND, Spinlock ID for Random Number Generator, min=0, max=31, default=12, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_RAND
#define PICO_SPINLOCK_ID_RAND 12
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_OS1, First Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=14, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_OS1, First Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=14, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_OS1
#define PICO_SPINLOCK_ID_OS1 14
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_OS2, Second Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=15, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_OS2, Second Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=15, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_OS2
#define PICO_SPINLOCK_ID_OS2 15
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_STRIPED_FIRST, Lowest Spinlock ID in the 'striped' range, min=0, max=31, default=16, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_STRIPED_FIRST, Lowest Spinlock ID in the 'striped' range, min=0, max=31, default=16, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_STRIPED_FIRST
#define PICO_SPINLOCK_ID_STRIPED_FIRST 16
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_STRIPED_LAST, Highest Spinlock ID in the 'striped' range, min=0, max=31, default=23, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_STRIPED_LAST, Highest Spinlock ID in the 'striped' range, min=0, max=31, default=23, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_STRIPED_LAST
#define PICO_SPINLOCK_ID_STRIPED_LAST 23
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_CLAIM_FREE_FIRST, Lowest Spinlock ID in the 'claim free' range, min=0, max=31, default=24, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_CLAIM_FREE_FIRST, Lowest Spinlock ID in the 'claim free' range, min=0, max=31, default=24, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_CLAIM_FREE_FIRST
#define PICO_SPINLOCK_ID_CLAIM_FREE_FIRST 24
#endif
@@ -80,7 +80,7 @@ static inline void atomic_thread_fence(uint x) {}
#warning PICO_SPINLOCK_ID_CLAIM_FREE_END has been renamed to PICO_SPINLOCK_ID_CLAIM_FREE_LAST
#endif
-/// PICO_CONFIG: PICO_SPINLOCK_ID_CLAIM_FREE_LAST, Highest Spinlock ID in the 'claim free' range, min=0, max=31, default=31, group=hardware_sync
+// PICO_CONFIG: PICO_SPINLOCK_ID_CLAIM_FREE_LAST, Highest Spinlock ID in the 'claim free' range, min=0, max=31, default=31, group=hardware_sync
#ifndef PICO_SPINLOCK_ID_CLAIM_FREE_LAST
#define PICO_SPINLOCK_ID_CLAIM_FREE_LAST 31
#endif
diff --git a/src/host/hardware_timer/BUILD.bazel b/src/host/hardware_timer/BUILD.bazel
index 57bc42555..4c255a925 100644
--- a/src/host/hardware_timer/BUILD.bazel
+++ b/src/host/hardware_timer/BUILD.bazel
@@ -15,7 +15,10 @@ cc_library(
defines = _DEFINES,
includes = ["include"],
target_compatible_with = ["//bazel/constraint:host"],
- visibility = ["//src/common/pico_time:__pkg__"],
+ visibility = [
+ "//src/common/pico_time:__pkg__",
+ "//src/host/pico_platform:__pkg__",
+ ],
deps = ["//src/common/pico_base_headers"],
)
diff --git a/src/host/pico_platform/BUILD.bazel b/src/host/pico_platform/BUILD.bazel
index 610a38352..c29a5bbaf 100644
--- a/src/host/pico_platform/BUILD.bazel
+++ b/src/host/pico_platform/BUILD.bazel
@@ -30,5 +30,6 @@ cc_library(
":pico_platform_internal",
":platform_defs",
"//src/common/pico_base_headers",
+ "//src/host/hardware_timer:hardware_timer_headers",
],
)
diff --git a/src/host/pico_platform/include/pico/platform.h b/src/host/pico_platform/include/pico/platform.h
index dca69f265..2854ab6f7 100644
--- a/src/host/pico_platform/include/pico/platform.h
+++ b/src/host/pico_platform/include/pico/platform.h
@@ -11,7 +11,7 @@
#include
#include
-#ifdef __unix__
+#if defined __unix__ && defined __GLIBC__
#include
@@ -47,7 +47,7 @@ extern void tight_loop_contents();
#define __STRING(x) #x
#endif
-#ifndef _MSC_VER
+#if !defined(_MSC_VER) || defined(__clang__)
#ifndef __noreturn
#define __noreturn __attribute((noreturn))
#endif
@@ -148,7 +148,11 @@ uint get_core_num();
static inline uint __get_current_exception(void) {
return 0;
+
}
+
+void busy_wait_at_least_cycles(uint32_t minimum_cycles);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/host/pico_platform/platform_base.c b/src/host/pico_platform/platform_base.c
index 25acbf1db..f7d2c95ff 100644
--- a/src/host/pico_platform/platform_base.c
+++ b/src/host/pico_platform/platform_base.c
@@ -7,9 +7,9 @@
#include
#include "pico.h"
+#include "hardware/timer.h"
PICO_WEAK_FUNCTION_DEF(tight_loop_contents)
-
void PICO_WEAK_FUNCTION_IMPL_NAME(tight_loop_contents)() {
}
@@ -45,4 +45,10 @@ void __breakpoint() {
#else
__builtin_trap();
#endif
-}
\ No newline at end of file
+}
+
+PICO_WEAK_FUNCTION_DEF(busy_wait_at_least_cycles)
+void PICO_WEAK_FUNCTION_IMPL_NAME(busy_wait_at_least_cycles)(uint32_t cycles) {
+ // fairly arbitrary; we'll use 125Mhz as a reference
+ busy_wait_us((cycles + 124)/125);
+}
diff --git a/src/host/pico_runtime/CMakeLists.txt b/src/host/pico_runtime/CMakeLists.txt
index da9a8a47e..dd4d67173 100644
--- a/src/host/pico_runtime/CMakeLists.txt
+++ b/src/host/pico_runtime/CMakeLists.txt
@@ -4,4 +4,7 @@ target_include_directories(pico_runtime_headers SYSTEM INTERFACE ${CMAKE_CURRENT
pico_mirrored_target_link_libraries(pico_runtime INTERFACE
pico_base
-)
\ No newline at end of file
+)
+
+function(pico_minimize_runtime TARGET)
+endfunction()
\ No newline at end of file
diff --git a/src/host/pico_time_adapter/include/pico/time_adapter.h b/src/host/pico_time_adapter/include/pico/time_adapter.h
index 14475c72e..74f8de22a 100644
--- a/src/host/pico_time_adapter/include/pico/time_adapter.h
+++ b/src/host/pico_time_adapter/include/pico/time_adapter.h
@@ -19,6 +19,7 @@ void ta_clear_force_irq(alarm_pool_timer_t *timer, uint hardware_alarm_num);
void ta_clear_irq(alarm_pool_timer_t *timer, uint hardware_alarm_num);
void ta_force_irq(alarm_pool_timer_t *timer, uint hardware_alarm_num);
void ta_set_timeout(alarm_pool_timer_t *timer, uint hardware_alarm_num, int64_t target);
+bool ta_wakes_up_on_or_before(alarm_pool_timer_t *timer, uint alarm_num, int64_t target);
void ta_enable_irq_handler(alarm_pool_timer_t *timer, uint hardware_alarm_num, void (*irq_handler)(void));
void ta_disable_irq_handler(alarm_pool_timer_t *timer, uint hardware_alarm_num, void (*irq_handler)(void));
void ta_hardware_alarm_claim(alarm_pool_timer_t *timer, uint hardware_alarm_num);
diff --git a/src/host/pico_time_adapter/time_adapter.c b/src/host/pico_time_adapter/time_adapter.c
index 1a5d7085f..e805b3017 100644
--- a/src/host/pico_time_adapter/time_adapter.c
+++ b/src/host/pico_time_adapter/time_adapter.c
@@ -27,6 +27,10 @@ PICO_WEAK_FUNCTION_DEF(ta_set_timeout)
void PICO_WEAK_FUNCTION_IMPL_NAME(ta_set_timeout)(alarm_pool_timer_t *timer, uint hardware_alarm_num, int64_t target) {
panic_unsupported();
}
+PICO_WEAK_FUNCTION_DEF(ta_wakes_up_on_or_before)
+bool PICO_WEAK_FUNCTION_IMPL_NAME(ta_wakes_up_on_or_before)(alarm_pool_timer_t *timer, uint hardware_alarm_num, int64_t target) {
+ panic_unsupported();
+}
PICO_WEAK_FUNCTION_DEF(ta_enable_irq_handler)
void PICO_WEAK_FUNCTION_IMPL_NAME(ta_enable_irq_handler)(alarm_pool_timer_t *timer, uint hardware_alarm_num, void (*irq_handler)(void)) {
panic_unsupported();
diff --git a/src/rp2040.cmake b/src/rp2040.cmake
index a0d97f4fc..59ef05d55 100644
--- a/src/rp2040.cmake
+++ b/src/rp2040.cmake
@@ -3,6 +3,7 @@
set(RP2_VARIANT_DIR ${CMAKE_CURRENT_LIST_DIR}/rp2040)
set(PICO_RP2040 "1" CACHE INTERNAL "")
set(PICO_RP2350 "0" CACHE INTERNAL "")
+set(PICO_32BIT "1" CACHE INTERNAL "")
set(PICO_RISCV "0" CACHE INTERNAL "")
set(PICO_ARM "1" CACHE INTERNAL "")
set(PICO_CMSIS_DEVICE "RP2040" CACHE INTERNAL "")
diff --git a/src/rp2040/boot_stage2/BUILD.bazel b/src/rp2040/boot_stage2/BUILD.bazel
index 65c9e76b2..56ed5f3c3 100644
--- a/src/rp2040/boot_stage2/BUILD.bazel
+++ b/src/rp2040/boot_stage2/BUILD.bazel
@@ -76,6 +76,11 @@ cc_binary(
copts = ["-fPIC"],
# Incompatible with section garbage collection.
features = ["-gc_sections"],
+ # Platforms will commonly depend on bootloader components in every
+ # binary via `link_extra_libs`, so we must drop these deps when
+ # building the bootloader binaries themselves in order to avoid a
+ # circular dependency.
+ link_extra_lib = "//bazel:empty_cc_lib",
linkopts = [
"-Wl,--no-gc-sections",
"-nostartfiles",
diff --git a/src/rp2040/boot_stage2/CMakeLists.txt b/src/rp2040/boot_stage2/CMakeLists.txt
index c5768785b..ba42256b7 100644
--- a/src/rp2040/boot_stage2/CMakeLists.txt
+++ b/src/rp2040/boot_stage2/CMakeLists.txt
@@ -30,7 +30,7 @@ pico_register_common_scope_var(PICO_DEFAULT_BOOT_STAGE2_FILE)
# needed by function below
set(PICO_BOOT_STAGE2_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
-add_library(boot_stage2_headers INTERFACE)
+pico_add_library(boot_stage2_headers)
target_include_directories(boot_stage2_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
# by convention the first source file name without extension is used for the binary info name
@@ -66,15 +66,12 @@ function(pico_define_boot_stage2 NAME SOURCES)
add_custom_command(OUTPUT ${ORIGINAL_BIN} DEPENDS ${NAME} COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${ORIGINAL_BIN}
VERBATIM)
- add_custom_target(${NAME}_padded_checksummed_asm DEPENDS ${PADDED_CHECKSUMMED_ASM})
add_custom_command(OUTPUT ${PADDED_CHECKSUMMED_ASM} DEPENDS ${ORIGINAL_BIN}
COMMAND ${Python3_EXECUTABLE} ${PICO_BOOT_STAGE2_DIR}/pad_checksum -s 0xffffffff ${ORIGINAL_BIN} ${PADDED_CHECKSUMMED_ASM}
VERBATIM)
- add_library(${NAME}_library INTERFACE)
- add_dependencies(${NAME}_library ${NAME}_padded_checksummed_asm)
- # not strictly (or indeed actually) a link library, but this avoids dependency cycle
- target_link_libraries(${NAME}_library INTERFACE ${PADDED_CHECKSUMMED_ASM})
+ add_library(${NAME}_library OBJECT ${PADDED_CHECKSUMMED_ASM})
+ target_link_libraries(${NAME}_library INTERFACE "$")
target_link_libraries(${NAME}_library INTERFACE boot_stage2_headers)
list(GET SOURCES 0 FIRST_SOURCE)
diff --git a/src/rp2040/boot_stage2/boot2_w25x10cl.S b/src/rp2040/boot_stage2/boot2_w25x10cl.S
index 9aa51ac57..b0e6a10fc 100644
--- a/src/rp2040/boot_stage2/boot2_w25x10cl.S
+++ b/src/rp2040/boot_stage2/boot2_w25x10cl.S
@@ -144,10 +144,10 @@ regular_func _stage2_boot
// status register and checking for the "RX FIFO Not Empty" flag to assert.
movs r1, #SSI_SR_RFNE_BITS
-00:
+1:
ldr r0, [r3, #SSI_SR_OFFSET] // Read status register
tst r0, r1 // RFNE status flag set?
- beq 00b // If not then wait
+ beq 1b // If not then wait
// At this point CN# will be deasserted and the SPI clock will not be running.
// The Winbond WX25X10CL device will be in continuous read, dual I/O mode and
diff --git a/src/rp2040/boot_stage2/boot_stage2.ld b/src/rp2040/boot_stage2/boot_stage2.ld
index f8669ab64..32978a16e 100644
--- a/src/rp2040/boot_stage2/boot_stage2.ld
+++ b/src/rp2040/boot_stage2/boot_stage2.ld
@@ -7,6 +7,7 @@ MEMORY {
SECTIONS {
. = ORIGIN(SRAM);
.text : {
+ _start = .; /* make LLVM happy */
*(.entry)
*(.text)
} >SRAM
diff --git a/src/rp2040/boot_stage2/include/boot_stage2/config.h b/src/rp2040/boot_stage2/include/boot_stage2/config.h
index e4d32628c..ba9bb1f8b 100644
--- a/src/rp2040/boot_stage2/include/boot_stage2/config.h
+++ b/src/rp2040/boot_stage2/include/boot_stage2/config.h
@@ -11,7 +11,7 @@
#include "pico.h"
-// PICO_CONFIG: PICO_BUILD_BOOT_STAGE2_NAME, The name of the boot stage 2 if selected by the build, group=boot_stage2
+// PICO_CONFIG: PICO_BUILD_BOOT_STAGE2_NAME, Name of the boot stage 2 if selected in the build system, group=boot_stage2
#ifdef PICO_BUILD_BOOT_STAGE2_NAME
#define _BOOT_STAGE2_SELECTED
#else
diff --git a/src/rp2040/hardware_regs/include/hardware/platform_defs.h b/src/rp2040/hardware_regs/include/hardware/platform_defs.h
index 54d9344c8..1d23b9d12 100644
--- a/src/rp2040/hardware_regs/include/hardware/platform_defs.h
+++ b/src/rp2040/hardware_regs/include/hardware/platform_defs.h
@@ -116,4 +116,6 @@
#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
#define VTABLE_FIRST_IRQ 16
+#define REG_FIELD_WIDTH(f) (f ## _MSB + 1 - f ## _LSB)
+
#endif
diff --git a/src/rp2040/pico_platform/include/pico/platform.h b/src/rp2040/pico_platform/include/pico/platform.h
index c28e2591d..47aa119a7 100644
--- a/src/rp2040/pico_platform/include/pico/platform.h
+++ b/src/rp2040/pico_platform/include/pico/platform.h
@@ -66,15 +66,15 @@
#define PICO_RP2040_B2_SUPPORTED 1
#endif
-// PICO_CONFIG: PICO_RP2350_A2_SUPPORTED, Whether to include any specific software support for RP2350 A2 revision, type=bool, default=1, advanced=true, group=pico_platform
-#ifndef PICO_RP2350_A2_SUPPORTED
-#define PICO_RP2350_A2_SUPPORTED 1
-#endif
-
#ifndef PICO_RAM_VECTOR_TABLE_SIZE
#define PICO_RAM_VECTOR_TABLE_SIZE (VTABLE_FIRST_IRQ + NUM_IRQS)
#endif
+// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group=pico_platform
+#ifndef PICO_CLKDIV_ROUND_NEAREST
+#define PICO_CLKDIV_ROUND_NEAREST 1
+#endif
+
#ifndef __ASSEMBLER__
/*! \brief No-op function for the body of tight loops
@@ -212,4 +212,4 @@ return a;
#endif // __ASSEMBLER__
-#endif
\ No newline at end of file
+#endif
diff --git a/src/rp2350-arm-s.cmake b/src/rp2350-arm-s.cmake
index 4941a1c3e..cd6d94e04 100644
--- a/src/rp2350-arm-s.cmake
+++ b/src/rp2350-arm-s.cmake
@@ -2,6 +2,7 @@
set(PICO_RP2040 "0" CACHE INTERNAL "")
set(PICO_RP2350 "1" CACHE INTERNAL "")
+set(PICO_32BIT "1" CACHE INTERNAL "")
set(PICO_RISCV "0" CACHE INTERNAL "")
set(PICO_ARM "1" CACHE INTERNAL "")
set(RP2_VARIANT_DIR ${CMAKE_CURRENT_LIST_DIR}/rp2350)
diff --git a/src/rp2350-riscv.cmake b/src/rp2350-riscv.cmake
index f62f6e4be..4856445d4 100644
--- a/src/rp2350-riscv.cmake
+++ b/src/rp2350-riscv.cmake
@@ -2,6 +2,7 @@
set(PICO_RP2040 "0" CACHE INTERNAL "")
set(PICO_RP2350 "1" CACHE INTERNAL "")
+set(PICO_32BIT "1" CACHE INTERNAL "")
set(PICO_RISCV "1" CACHE INTERNAL "")
set(PICO_ARM "0" CACHE INTERNAL "")
set(RP2_VARIANT_DIR ${CMAKE_CURRENT_LIST_DIR}/rp2350)
diff --git a/src/rp2350/boot_stage2/BUILD.bazel b/src/rp2350/boot_stage2/BUILD.bazel
index e831c638c..42e4249d1 100644
--- a/src/rp2350/boot_stage2/BUILD.bazel
+++ b/src/rp2350/boot_stage2/BUILD.bazel
@@ -76,6 +76,11 @@ cc_binary(
copts = ["-fPIC"],
# Incompatible with section garbage collection.
features = ["-gc_sections"],
+ # Platforms will commonly depend on bootloader components in every
+ # binary via `link_extra_libs`, so we must drop these deps when
+ # building the bootloader binaries themselves in order to avoid a
+ # circular dependency.
+ link_extra_lib = "//bazel:empty_cc_lib",
linkopts = [
"-Wl,--no-gc-sections",
"-nostartfiles",
diff --git a/src/rp2350/boot_stage2/CMakeLists.txt b/src/rp2350/boot_stage2/CMakeLists.txt
index bf41eb233..e878ccc5b 100644
--- a/src/rp2350/boot_stage2/CMakeLists.txt
+++ b/src/rp2350/boot_stage2/CMakeLists.txt
@@ -40,9 +40,9 @@ function(pico_define_boot_stage2 NAME SOURCES)
)
# todo bit of an abstraction failure - revisit for Clang support anyway
- if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ if (PICO_C_COMPILER_IS_CLANG)
target_link_options(${NAME} PRIVATE "-nostdlib")
- else ()
+ elseif (PICO_C_COMPILER_IS_GNU)
target_link_options(${NAME} PRIVATE "--specs=nosys.specs")
target_link_options(${NAME} PRIVATE "-nostartfiles")
endif ()
@@ -63,17 +63,15 @@ function(pico_define_boot_stage2 NAME SOURCES)
find_package (Python3 REQUIRED COMPONENTS Interpreter)
add_custom_target(${NAME}_bin DEPENDS ${ORIGINAL_BIN})
- add_custom_command(OUTPUT ${ORIGINAL_BIN} DEPENDS ${NAME} COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${ORIGINAL_BIN})
+ add_custom_command(OUTPUT ${ORIGINAL_BIN} DEPENDS ${NAME} COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${ORIGINAL_BIN}
+ VERBATIM)
- add_custom_target(${NAME}_padded_checksummed_asm DEPENDS ${PADDED_CHECKSUMMED_ASM})
add_custom_command(OUTPUT ${PADDED_CHECKSUMMED_ASM} DEPENDS ${ORIGINAL_BIN}
COMMAND ${Python3_EXECUTABLE} ${PICO_BOOT_STAGE2_DIR}/pad_checksum -s 0xffffffff -a $ ${ORIGINAL_BIN} ${PADDED_CHECKSUMMED_ASM}
- )
+ VERBATIM)
- add_library(${NAME}_library INTERFACE)
- add_dependencies(${NAME}_library ${NAME}_padded_checksummed_asm)
- # not strictly (or indeed actually) a link library, but this avoids dependency cycle
- target_link_libraries(${NAME}_library INTERFACE ${PADDED_CHECKSUMMED_ASM})
+ add_library(${NAME}_library OBJECT ${PADDED_CHECKSUMMED_ASM})
+ target_link_libraries(${NAME}_library INTERFACE "$")
target_link_libraries(${NAME}_library INTERFACE boot_stage2_headers)
list(GET SOURCES 0 FIRST_SOURCE)
diff --git a/src/rp2350/boot_stage2/boot_stage2.ld b/src/rp2350/boot_stage2/boot_stage2.ld
index 0162414a8..ee1bce466 100644
--- a/src/rp2350/boot_stage2/boot_stage2.ld
+++ b/src/rp2350/boot_stage2/boot_stage2.ld
@@ -7,6 +7,7 @@ MEMORY {
SECTIONS {
. = ORIGIN(SRAM);
.text : {
+ _start = .; /* make LLVM happy */
*(.entry)
*(.text)
} >SRAM
diff --git a/src/rp2350/hardware_regs/include/hardware/platform_defs.h b/src/rp2350/hardware_regs/include/hardware/platform_defs.h
index 8ea4fadfb..bd8b68a9f 100644
--- a/src/rp2350/hardware_regs/include/hardware/platform_defs.h
+++ b/src/rp2350/hardware_regs/include/hardware/platform_defs.h
@@ -74,7 +74,7 @@
#define HAS_RP2350_TRNG 1
#define HAS_HSTX 1
-// PICO_CONFIG: XOSC_HZ, The crystal oscillator frequency in Hz, type=int, default=12000000, advanced=true, group=hardware_base
+// PICO_CONFIG: XOSC_HZ, Crystal oscillator frequency in Hz, type=int, default=12000000, advanced=true, group=hardware_base
// NOTE: The system and USB clocks are generated from the frequency using two PLLs.
// If you override this define, or SYS_CLK_HZ/USB_CLK_HZ below, you will *also* need to add your own adjusted PLL set-up defines to
// override the defaults which live in src/rp2_common/hardware_clocks/include/hardware/clocks.h
@@ -89,7 +89,7 @@
#endif
#endif
-// PICO_CONFIG: SYS_CLK_HZ, The system operating frequency in Hz, type=int, default=150000000, advanced=true, group=hardware_base
+// PICO_CONFIG: SYS_CLK_HZ, System operating frequency in Hz, type=int, default=150000000, advanced=true, group=hardware_base
#ifndef SYS_CLK_HZ
#ifdef SYS_CLK_KHZ
#define SYS_CLK_HZ ((SYS_CLK_KHZ) * _u(1000))
@@ -160,4 +160,6 @@
#endif
#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
+#define REG_FIELD_WIDTH(f) (f ## _MSB + 1 - f ## _LSB)
+
#endif
diff --git a/src/rp2350/pico_platform/CMakeLists.txt b/src/rp2350/pico_platform/CMakeLists.txt
index 7f13f5733..80a5103e3 100644
--- a/src/rp2350/pico_platform/CMakeLists.txt
+++ b/src/rp2350/pico_platform/CMakeLists.txt
@@ -29,6 +29,9 @@ if (NOT TARGET pico_platform)
hardware_dcp
hardware_rcp
)
+ if (PICO_RISCV)
+ pico_mirrored_target_link_libraries(pico_platform INTERFACE hardware_hazard3)
+ endif()
endif()
function(pico_add_platform_library TARGET)
diff --git a/src/rp2350/pico_platform/include/pico/asm_helper.S b/src/rp2350/pico_platform/include/pico/asm_helper.S
index 7ff55c44c..b8eeb53c7 100644
--- a/src/rp2350/pico_platform/include/pico/asm_helper.S
+++ b/src/rp2350/pico_platform/include/pico/asm_helper.S
@@ -6,12 +6,17 @@
#include "pico.h"
+#ifdef __riscv
+// Get macros for convenient use of Hazard3 instructions without binutils support
+#include "hardware/hazard3/instructions.h"
+#endif
+
#if !PICO_ASSEMBLER_IS_CLANG
#define apsr_nzcv r15
#endif
-# note we don't do this by default in this file for backwards comaptibility with user code
-# that may include this file, but not use unified syntax. Note that this macro does equivalent
-# setup to the pico_default_asm macro for inline assembly in C code.
+// note we don't do this by default in this file for backwards comaptibility with user code
+// that may include this file, but not use unified syntax. Note that this macro does equivalent
+// setup to the pico_default_asm macro for inline assembly in C code.
.macro pico_default_asm_setup
#ifndef __riscv
.syntax unified
@@ -60,28 +65,7 @@ weak_func WRAPPER_FUNC_NAME(\x)
.word \func + \offset
.endm
-# backwards compatibility
+// backwards compatibility
.macro __pre_init func, priority_string1
__pre_init_with_offset func, 0, priority_string1
.endm
-
-#ifdef __riscv
-// rd = (rs1 >> rs2[4:0]) & ~(-1 << nbits)
-.macro h3.bextm rd rs1 rs2 nbits
-.if (\nbits < 1) || (\nbits > 8)
-.err
-.endif
- .insn r 0x0b, 0x4, (((\nbits - 1) & 0x7 ) << 1), \rd, \rs1, \rs2
-.endm
-
-// rd = (rs1 >> shamt) & ~(-1 << nbits)
-.macro h3.bextmi rd rs1 shamt nbits
-.if (\nbits < 1) || (\nbits > 8)
-.err
-.endif
-.if (\shamt < 0) || (\shamt > 31)
-.err
-.endif
- .insn i 0x0b, 0x4, \rd, \rs1, (\shamt & 0x1f) | (((\nbits - 1) & 0x7 ) << 6)
-.endm
-#endif
\ No newline at end of file
diff --git a/src/rp2350/pico_platform/include/pico/platform.h b/src/rp2350/pico_platform/include/pico/platform.h
index 9fab28cdf..24fec75bb 100644
--- a/src/rp2350/pico_platform/include/pico/platform.h
+++ b/src/rp2350/pico_platform/include/pico/platform.h
@@ -30,6 +30,14 @@
#endif
// PICO_CONFIG: PICO_RP2350A, Whether the current board has an RP2350 in an A (30 GPIO) package, type=bool, default=Usually provided via board header, group=pico_platform
+#if 0 // make tooling checks happy
+#define PICO_RP2350A 0
+#endif
+
+// PICO_CONFIG: PICO_RP2350_A2_SUPPORTED, Whether to include any specific software support for RP2350 A2 revision, type=bool, default=1, advanced=true, group=pico_platform
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
// PICO_CONFIG: PICO_STACK_SIZE, Minimum amount of stack space reserved in the linker script for each core. See also PICO_CORE1_STACK_SIZE, min=0x100, default=0x800, advanced=true, group=pico_platform
#ifndef PICO_STACK_SIZE
@@ -55,6 +63,11 @@
#define PICO_USE_STACK_GUARDS 0
#endif
+// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group=pico_platform
+#ifndef PICO_CLKDIV_ROUND_NEAREST
+#define PICO_CLKDIV_ROUND_NEAREST 1
+#endif
+
#ifndef __ASSEMBLER__
/*! \brief No-op function for the body of tight loops
@@ -99,12 +112,10 @@ static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) {
);
}
-// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=platform dependent, advanced=true, group=pico_runtime
+// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
#ifndef PICO_NO_FPGA_CHECK
-#if !PICO_RP2040
#define PICO_NO_FPGA_CHECK 1
#endif
-#endif
// PICO_CONFIG: PICO_NO_SIM_CHECK, Remove the SIM platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
#ifndef PICO_NO_SIM_CHECK
@@ -246,7 +257,7 @@ static inline uint8_t rp2040_rom_version(void) {
*/
__force_inline static int32_t __mul_instruction(int32_t a, int32_t b) {
#ifdef __riscv
- __asm ("mul %0, %0, %1" : "+l" (a) : "l" (b) : );
+ __asm ("mul %0, %0, %1" : "+r" (a) : "r" (b) : );
#else
pico_default_asm ("muls %0, %1" : "+l" (a) : "l" (b) : "cc");
#endif
diff --git a/src/rp2350/pico_platform/platform.c b/src/rp2350/pico_platform/platform.c
index 912cc53ff..97960478f 100644
--- a/src/rp2350/pico_platform/platform.c
+++ b/src/rp2350/pico_platform/platform.c
@@ -28,7 +28,7 @@ bool __attribute__((weak)) running_in_sim(void) {
}
#endif
-#define MANUFACTURER_RPI 0x927
+#define MANUFACTURER_RPI 0x926
#define PART_RP4 0x4
uint8_t rp2350_chip_version(void) {
diff --git a/src/rp2350/rp2350a_interface_pins.json b/src/rp2350/rp2350a_interface_pins.json
new file mode 100644
index 000000000..7869d2aad
--- /dev/null
+++ b/src/rp2350/rp2350a_interface_pins.json
@@ -0,0 +1,95 @@
+{
+ "interfaces": {
+ "UART": {
+ "instances": {
+ "0": {
+ "TX": [0, 2, 12, 14, 16, 18, 28],
+ "RX": [1, 3, 13, 15, 17, 19, 29],
+ "CTS": [2, 14, 18],
+ "RTS": [3, 15, 19]
+ },
+ "1": {
+ "TX": [4, 6, 8, 10, 20, 22, 24, 26],
+ "RX": [5, 7, 9, 11, 21, 23, 25, 27],
+ "CTS": [6, 10, 22, 26],
+ "RTS": [7, 11, 23, 27]
+ }
+ },
+ "expected_functions": {
+ "one_of": ["TX", "RX"]
+ }
+ },
+ "I2C": {
+ "instances": {
+ "0": {
+ "SDA": [0, 4, 8, 12, 16, 20, 24, 28],
+ "SCL": [1, 5, 9, 13, 17, 21, 25, 29]
+ },
+ "1": {
+ "SDA": [2, 6, 10, 14, 18, 22, 26],
+ "SCL": [3, 7, 11, 15, 19, 23, 27]
+ }
+ },
+ "expected_functions": {
+ "required": ["SDA", "SCL"]
+ }
+ },
+ "SPI": {
+ "instances": {
+ "0": {
+ "RX": [0, 4, 16, 20],
+ "CSN": [1, 5, 17, 21],
+ "SCK": [2, 6, 18, 22],
+ "TX": [3, 7, 19, 23]
+ },
+ "1": {
+ "RX": [8, 12, 24, 28],
+ "CSN": [9, 13, 25, 29],
+ "SCK": [10, 14, 26],
+ "TX": [11, 15, 27]
+ }
+ },
+ "expected_functions": {
+ "required": ["SCK"],
+ "one_of": ["RX", "TX"]
+ }
+ },
+ "PWM": {
+ "instances": {
+ "0": {
+ "A": [0, 16],
+ "B": [1, 17]
+ },
+ "1": {
+ "A": [2, 18],
+ "B": [3, 19]
+ },
+ "2": {
+ "A": [4, 20],
+ "B": [5, 21]
+ },
+ "3": {
+ "A": [6, 22],
+ "B": [7, 23]
+ },
+ "4": {
+ "A": [8, 24],
+ "B": [9, 25]
+ },
+ "5": {
+ "A": [10, 26],
+ "B": [11, 27]
+ },
+ "6": {
+ "A": [12, 28],
+ "B": [13, 29]
+ },
+ "7": {
+ "A": [14],
+ "B": [15]
+ }
+ }
+ }
+ },
+ "pins": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
+}
diff --git a/src/rp2350/rp2350b_interface_pins.json b/src/rp2350/rp2350b_interface_pins.json
new file mode 100644
index 000000000..ee90ad27f
--- /dev/null
+++ b/src/rp2350/rp2350b_interface_pins.json
@@ -0,0 +1,111 @@
+{
+ "interfaces": {
+ "UART": {
+ "instances": {
+ "0": {
+ "TX": [0, 2, 12, 14, 16, 18, 28, 30, 32, 34, 44, 46],
+ "RX": [1, 3, 13, 15, 17, 19, 29, 31, 33, 35, 45, 47],
+ "CTS": [2, 14, 18, 30, 34, 46],
+ "RTS": [3, 15, 19, 31, 35, 47]
+ },
+ "1": {
+ "TX": [4, 6, 8, 10, 20, 22, 24, 26, 36, 38, 40, 42],
+ "RX": [5, 7, 9, 11, 21, 23, 25, 27, 37, 39, 41, 43],
+ "CTS": [6, 10, 22, 26, 38, 42],
+ "RTS": [7, 11, 23, 27, 39, 43]
+ }
+ },
+ "expected_functions": {
+ "one_of": ["TX", "RX"]
+ }
+ },
+ "I2C": {
+ "instances": {
+ "0": {
+ "SDA": [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44],
+ "SCL": [1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45]
+ },
+ "1": {
+ "SDA": [2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46],
+ "SCL": [3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47]
+ }
+ },
+ "expected_functions": {
+ "required": ["SDA", "SCL"]
+ }
+ },
+ "SPI": {
+ "instances": {
+ "0": {
+ "RX": [0, 4, 16, 20, 32, 36],
+ "CSN": [1, 5, 17, 21, 33, 37],
+ "SCK": [2, 6, 18, 22, 34, 38],
+ "TX": [3, 7, 19, 23, 35, 39]
+ },
+ "1": {
+ "RX": [8, 12, 24, 28, 40, 44],
+ "CSN": [9, 13, 25, 29, 41, 45],
+ "SCK": [10, 14, 26, 30, 42, 46],
+ "TX": [11, 15, 27, 31, 43, 47]
+ }
+ },
+ "expected_functions": {
+ "required": ["SCK"],
+ "one_of": ["RX", "TX"]
+ }
+ },
+ "PWM": {
+ "instances": {
+ "0": {
+ "A": [0, 16],
+ "B": [1, 17]
+ },
+ "1": {
+ "A": [2, 18],
+ "B": [3, 19]
+ },
+ "2": {
+ "A": [4, 20],
+ "B": [5, 21]
+ },
+ "3": {
+ "A": [6, 22],
+ "B": [7, 23]
+ },
+ "4": {
+ "A": [8, 24],
+ "B": [9, 25]
+ },
+ "5": {
+ "A": [10, 26],
+ "B": [11, 27]
+ },
+ "6": {
+ "A": [12, 28],
+ "B": [13, 29]
+ },
+ "7": {
+ "A": [14, 30],
+ "B": [15, 31]
+ },
+ "8": {
+ "A": [32, 40],
+ "B": [33, 41]
+ },
+ "9": {
+ "A": [34, 42],
+ "B": [35, 43]
+ },
+ "10": {
+ "A": [36, 44],
+ "B": [37, 45]
+ },
+ "11": {
+ "A": [38, 46],
+ "B": [39, 47]
+ }
+ }
+ }
+ },
+ "pins": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
+}
diff --git a/src/rp2_common/boot_bootrom_headers/BUILD.bazel b/src/rp2_common/boot_bootrom_headers/BUILD.bazel
new file mode 100644
index 000000000..51b5f7b77
--- /dev/null
+++ b/src/rp2_common/boot_bootrom_headers/BUILD.bazel
@@ -0,0 +1,10 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "boot_bootrom_headers",
+ hdrs = ["include/boot/bootrom_constants.h"],
+ includes = ["include"],
+ deps = [
+ "//src:pico_platform_internal",
+ ],
+)
diff --git a/src/rp2_common/boot_bootrom_headers/CMakeLists.txt b/src/rp2_common/boot_bootrom_headers/CMakeLists.txt
new file mode 100644
index 000000000..99bdfefa6
--- /dev/null
+++ b/src/rp2_common/boot_bootrom_headers/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(boot_bootrom_headers INTERFACE)
+target_include_directories(boot_bootrom_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
diff --git a/src/rp2_common/boot_bootrom_headers/include/boot/bootrom_constants.h b/src/rp2_common/boot_bootrom_headers/include/boot/bootrom_constants.h
new file mode 100644
index 000000000..c1107f66b
--- /dev/null
+++ b/src/rp2_common/boot_bootrom_headers/include/boot/bootrom_constants.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _BOOT_BOOTROM_CONSTANTS_H
+#define _BOOT_BOOTROM_CONSTANTS_H
+
+#ifndef NO_PICO_PLATFORM
+#include "pico/platform.h"
+#endif
+
+// ROOT ADDRESSES
+#define BOOTROM_MAGIC_OFFSET 0x10
+#define BOOTROM_FUNC_TABLE_OFFSET 0x14
+#if PICO_RP2040
+#define BOOTROM_DATA_TABLE_OFFSET 0x16
+#endif
+
+#if PICO_RP2040
+#define BOOTROM_VTABLE_OFFSET 0x00
+#define BOOTROM_TABLE_LOOKUP_OFFSET 0x18
+#else
+#define BOOTROM_WELL_KNOWN_PTR_SIZE 2
+#if defined(__riscv)
+#define BOOTROM_ENTRY_OFFSET 0x7dfc
+#define BOOTROM_TABLE_LOOKUP_ENTRY_OFFSET (BOOTROM_ENTRY_OFFSET - BOOTROM_WELL_KNOWN_PTR_SIZE)
+#define BOOTROM_TABLE_LOOKUP_OFFSET (BOOTROM_ENTRY_OFFSET - BOOTROM_WELL_KNOWN_PTR_SIZE*2)
+#else
+#define BOOTROM_VTABLE_OFFSET 0x00
+#define BOOTROM_TABLE_LOOKUP_OFFSET (BOOTROM_FUNC_TABLE_OFFSET + BOOTROM_WELL_KNOWN_PTR_SIZE)
+#endif
+#endif
+
+#if !PICO_RP2040 || PICO_COMBINED_DOCS
+
+#define BOOTROM_OK 0
+//#define BOOTROM_ERROR_TIMEOUT (-1)
+//#define BOOTROM_ERROR_GENERIC (-2)
+//#define BOOTROM_ERROR_NO_DATA (-3) // E.g. read from an empty buffer/FIFO
+#define BOOTROM_ERROR_NOT_PERMITTED (-4) // Permission violation e.g. write to read-only flash partition
+#define BOOTROM_ERROR_INVALID_ARG (-5) // Argument is outside of range of supported values`
+//#define BOOTROM_ERROR_IO (-6)
+//#define BOOTROM_ERROR_BADAUTH (-7)
+//#define BOOTROM_ERROR_CONNECT_FAILED (-8)
+//#define BOOTROM_ERROR_INSUFFICIENT_RESOURCES (-9) // Dynamic allocation of resources failed
+#define BOOTROM_ERROR_INVALID_ADDRESS (-10) // Address argument was out-of-bounds or was determined to be an address that the caller may not access
+#define BOOTROM_ERROR_BAD_ALIGNMENT (-11) // Address modulo transfer chunk size was nonzero (e.g. word-aligned transfer with address % 4 != 0)
+#define BOOTROM_ERROR_INVALID_STATE (-12) // Something happened or failed to happen in the past, and consequently we (currently) can't service the request
+#define BOOTROM_ERROR_BUFFER_TOO_SMALL (-13) // A user-allocated buffer was too small to hold the result or working state of this function
+#define BOOTROM_ERROR_PRECONDITION_NOT_MET (-14) // This call failed because another ROM function must be called first
+#define BOOTROM_ERROR_MODIFIED_DATA (-15) // Cached data was determined to be inconsistent with the full version of the data it was calculated from
+#define BOOTROM_ERROR_INVALID_DATA (-16) // A data structure failed to validate
+#define BOOTROM_ERROR_NOT_FOUND (-17) // Attempted to access something that does not exist; or, a search failed
+#define BOOTROM_ERROR_UNSUPPORTED_MODIFICATION (-18) // Write is impossible based on previous writes; e.g. attempted to clear an OTP bit
+#define BOOTROM_ERROR_LOCK_REQUIRED (-19) // A required lock is not owned
+#define BOOTROM_ERROR_LAST (-19)
+
+#define RT_FLAG_FUNC_RISCV 0x0001
+#define RT_FLAG_FUNC_RISCV_FAR 0x0003
+#define RT_FLAG_FUNC_ARM_SEC 0x0004
+// reserved for 32-bit pointer: 0x0008
+#define RT_FLAG_FUNC_ARM_NONSEC 0x0010
+// reserved for 32-bit pointer: 0x0020
+#define RT_FLAG_DATA 0x0040
+// reserved for 32-bit pointer: 0x0080
+
+#define PARTITION_TABLE_MAX_PARTITIONS 16
+// note this is deliberately > MAX_PARTITIONs is likely to be, and also -1 as a signed byte
+#define PARTITION_TABLE_NO_PARTITION_INDEX 0xff
+
+// todo these are duplicated in picoboot_constants.h
+// values 0-7 are secure/non-secure
+#define BOOT_TYPE_NORMAL 0
+#define BOOT_TYPE_BOOTSEL 2
+#define BOOT_TYPE_RAM_IMAGE 3
+#define BOOT_TYPE_FLASH_UPDATE 4
+
+// values 8-15 are secure only
+#define BOOT_TYPE_PC_SP 0xd
+
+// ORed in if a bootloader chained into the image
+#define BOOT_TYPE_CHAINED_FLAG 0x80
+
+// call from NS to S
+#ifndef __riscv
+#define BOOTROM_API_CALLBACK_secure_call 0
+#endif
+#define BOOTROM_API_CALLBACK_COUNT 1
+
+#define BOOTROM_LOCK_SHA_256 0
+#define BOOTROM_LOCK_FLASH_OP 1
+#define BOOTROM_LOCK_OTP 2
+#define BOOTROM_LOCK_MAX 2
+
+#define BOOTROM_LOCK_ENABLE 7
+
+#define BOOT_PARTITION_NONE (-1)
+#define BOOT_PARTITION_SLOT0 (-2)
+#define BOOT_PARTITION_SLOT1 (-3)
+#define BOOT_PARTITION_WINDOW (-4)
+
+#define BOOT_DIAGNOSTIC_WINDOW_SEARCHED 0x01
+// note if both BOOT_DIAGNOSTIC_INVALID_BLOCK_LOOP and BOOT_DIAGNOSTIC_VALID_BLOCK_LOOP then the block loop was valid
+// but it has a PARTITION_TABLE which while it passed the initial verification (and hash/sig) had invalid contents
+// (discovered when it was later loaded)
+#define BOOT_DIAGNOSTIC_INVALID_BLOCK_LOOP 0x02
+#define BOOT_DIAGNOSTIC_VALID_BLOCK_LOOP 0x04
+#define BOOT_DIAGNOSTIC_VALID_IMAGE_DEF 0x08
+#define BOOT_DIAGNOSTIC_HAS_PARTITION_TABLE 0x10
+#define BOOT_DIAGNOSTIC_CONSIDERED 0x20
+#define BOOT_DIAGNOSTIC_CHOSEN 0x40
+#define BOOT_DIAGNOSTIC_PARTITION_TABLE_LSB 7
+#define BOOT_DIAGNOSTIC_PARTITION_TABLE_MATCHING_KEY_FOR_VERIFY 0x80
+#define BOOT_DIAGNOSTIC_PARTITION_TABLE_HASH_FOR_VERIFY 0x100
+#define BOOT_DIAGNOSTIC_PARTITION_TABLE_VERIFIED_OK 0x200
+#define BOOT_DIAGNOSTIC_IMAGE_DEF_LSB 10
+#define BOOT_DIAGNOSTIC_IMAGE_DEF_MATCHING_KEY_FOR_VERIFY 0x400
+#define BOOT_DIAGNOSTIC_IMAGE_DEF_HASH_FOR_VERIFY 0x800
+#define BOOT_DIAGNOSTIC_IMAGE_DEF_VERIFIED_OK 0x1000
+
+#define BOOT_DIAGNOSTIC_LOAD_MAP_ENTRIES_LOADED 0x2000
+#define BOOT_DIAGNOSTIC_IMAGE_LAUNCHED 0x4000
+#define BOOT_DIAGNOSTIC_IMAGE_CONDITION_FAILURE 0x8000
+
+#define BOOT_PARSED_BLOCK_DIAGNOSTIC_MATCHING_KEY_FOR_VERIFY 0x1 // if this is present and VERIFIED_OK isn't the sig check failed
+#define BOOT_PARSED_BLOCK_DIAGNOSTIC_HASH_FOR_VERIFY 0x2 // if this is present and VERIFIED_OL isn't then hash check failed
+#define BOOT_PARSED_BLOCK_DIAGNOSTIC_VERIFIED_OK 0x4
+
+#define BOOT_TBYB_AND_UPDATE_FLAG_BUY_PENDING 0x1
+#define BOOT_TBYB_AND_UPDATE_FLAG_OTP_VERSION_APPLIED 0x2
+#define BOOT_TBYB_AND_UPDATE_FLAG_OTHER_ERASED 0x4
+
+#ifndef __ASSEMBLER__
+// Limited to 3 arguments in case of varm multiplex hint (trashes Arm r3)
+typedef int (*bootrom_api_callback_generic_t)(uint32_t r0, uint32_t r1, uint32_t r2);
+// Return negative for error, else number of bytes transferred:
+//typedef int (*bootrom_api_callback_stdout_put_blocking_t)(const uint8_t *buffer, uint32_t size);
+//typedef int (*bootrom_api_callback_stdin_get_t)(uint8_t *buffer, uint32_t size);
+//typedef void (*bootrom_api_callback_core1_security_setup_t)(void);
+#endif
+
+#endif
+
+/*! \brief Return a bootrom lookup code based on two ASCII characters
+ * \ingroup pico_bootrom
+ *
+ * These codes are uses to lookup data or function addresses in the bootrom
+ *
+ * \param c1 the first character
+ * \param c2 the second character
+ * \return the 'code' to use in rom_func_lookup() or rom_data_lookup()
+ */
+#define ROM_TABLE_CODE(c1, c2) ((c1) | ((c2) << 8))
+
+// ROM FUNCTIONS
+
+// RP2040 & RP2350
+#define ROM_DATA_SOFTWARE_GIT_REVISION ROM_TABLE_CODE('G', 'R')
+#define ROM_FUNC_FLASH_ENTER_CMD_XIP ROM_TABLE_CODE('C', 'X')
+#define ROM_FUNC_FLASH_EXIT_XIP ROM_TABLE_CODE('E', 'X')
+#define ROM_FUNC_FLASH_FLUSH_CACHE ROM_TABLE_CODE('F', 'C')
+#define ROM_FUNC_CONNECT_INTERNAL_FLASH ROM_TABLE_CODE('I', 'F')
+#define ROM_FUNC_FLASH_RANGE_ERASE ROM_TABLE_CODE('R', 'E')
+#define ROM_FUNC_FLASH_RANGE_PROGRAM ROM_TABLE_CODE('R', 'P')
+
+
+#if PICO_RP2040
+// RP2040 only
+#define ROM_FUNC_MEMCPY44 ROM_TABLE_CODE('C', '4')
+#define ROM_DATA_COPYRIGHT ROM_TABLE_CODE('C', 'R')
+#define ROM_FUNC_CLZ32 ROM_TABLE_CODE('L', '3')
+#define ROM_FUNC_MEMCPY ROM_TABLE_CODE('M', 'C')
+#define ROM_FUNC_MEMSET ROM_TABLE_CODE('M', 'S')
+#define ROM_FUNC_POPCOUNT32 ROM_TABLE_CODE('P', '3')
+#define ROM_FUNC_REVERSE32 ROM_TABLE_CODE('R', '3')
+#define ROM_FUNC_MEMSET4 ROM_TABLE_CODE('S', '4')
+#define ROM_FUNC_CTZ32 ROM_TABLE_CODE('T', '3')
+#define ROM_FUNC_RESET_USB_BOOT ROM_TABLE_CODE('U', 'B')
+#endif
+
+#if !PICO_RP2040 || PICO_COMBINED_DOCS
+// RP2350 only
+#define ROM_FUNC_PICK_AB_PARTITION ROM_TABLE_CODE('A', 'B')
+#define ROM_FUNC_CHAIN_IMAGE ROM_TABLE_CODE('C', 'I')
+#define ROM_FUNC_EXPLICIT_BUY ROM_TABLE_CODE('E', 'B')
+#define ROM_FUNC_FLASH_RUNTIME_TO_STORAGE_ADDR ROM_TABLE_CODE('F', 'A')
+#define ROM_DATA_FLASH_DEVINFO16_PTR ROM_TABLE_CODE('F', 'D')
+#define ROM_FUNC_FLASH_OP ROM_TABLE_CODE('F', 'O')
+#define ROM_FUNC_GET_B_PARTITION ROM_TABLE_CODE('G', 'B')
+#define ROM_FUNC_GET_PARTITION_TABLE_INFO ROM_TABLE_CODE('G', 'P')
+#define ROM_FUNC_GET_SYS_INFO ROM_TABLE_CODE('G', 'S')
+#define ROM_FUNC_GET_UF2_TARGET_PARTITION ROM_TABLE_CODE('G', 'U')
+#define ROM_FUNC_LOAD_PARTITION_TABLE ROM_TABLE_CODE('L', 'P')
+#define ROM_FUNC_OTP_ACCESS ROM_TABLE_CODE('O', 'A')
+#define ROM_DATA_PARTITION_TABLE_PTR ROM_TABLE_CODE('P', 'T')
+#define ROM_FUNC_FLASH_RESET_ADDRESS_TRANS ROM_TABLE_CODE('R', 'A')
+#define ROM_FUNC_REBOOT ROM_TABLE_CODE('R', 'B')
+#define ROM_FUNC_SET_ROM_CALLBACK ROM_TABLE_CODE('R', 'C')
+#define ROM_FUNC_SECURE_CALL ROM_TABLE_CODE('S', 'C')
+#define ROM_FUNC_SET_NS_API_PERMISSION ROM_TABLE_CODE('S', 'P')
+#define ROM_FUNC_BOOTROM_STATE_RESET ROM_TABLE_CODE('S', 'R')
+#define ROM_FUNC_SET_BOOTROM_STACK ROM_TABLE_CODE('S', 'S')
+#define ROM_DATA_SAVED_XIP_SETUP_FUNC_PTR ROM_TABLE_CODE('X', 'F')
+#define ROM_FUNC_FLASH_SELECT_XIP_READ_MODE ROM_TABLE_CODE('X', 'M')
+#define ROM_FUNC_VALIDATE_NS_BUFFER ROM_TABLE_CODE('V', 'B')
+#endif
+
+// these form a bit set
+#define BOOTROM_STATE_RESET_CURRENT_CORE 0x01
+#define BOOTROM_STATE_RESET_OTHER_CORE 0x02
+#define BOOTROM_STATE_RESET_GLOBAL_STATE 0x04 // reset any global state (e.g. permissions)
+
+// partition level stuff is returned first (note PT_INFO flags is only 16 bits)
+
+// 3 words: pt_count, unpartitioned_perm_loc, unpartioned_perm_flags
+#define PT_INFO_PT_INFO 0x0001
+#define PT_INFO_SINGLE_PARTITION 0x8000 // marker to just include a single partition in the results)
+
+// then in order per partition selected
+
+// 2 words: unpartitioned_perm_loc, unpartioned_perm_flags
+#define PT_INFO_PARTITION_LOCATION_AND_FLAGS 0x0010
+// 2 words: id lsb first
+#define PT_INFO_PARTITION_ID 0x0020
+// n+1 words: n, family_id...
+#define PT_INFO_PARTITION_FAMILY_IDS 0x0040
+// (n+3)/4 words... bytes are: n (len), c0, c1, ... cn-1 padded to word boundary with zeroes
+#define PT_INFO_PARTITION_NAME 0x0080
+
+// items are returned in order
+// 3 words package_id, device_id, wafer_id
+#define SYS_INFO_CHIP_INFO 0x0001
+// 1 word: chip specific critical bits
+#define SYS_INFO_CRITICAL 0x0002
+// 1 word: bytes: cpu_type, supported_cpu_type_bitfield
+#define SYS_INFO_CPU_INFO 0x0004
+// 1 word: same as FLASH_DEVINFO row in OTP
+#define SYS_INFO_FLASH_DEV_INFO 0x0008
+// 4 words
+#define SYS_INFO_BOOT_RANDOM 0x0010
+// 2 words lsb first
+#define SYS_INFO_NONCE 0x0020
+// 4 words boot_info, boot_diagnostic, boot_param0, boot_param1
+#define SYS_INFO_BOOT_INFO 0x0040
+
+#define BOOTROM_NS_API_get_sys_info 0
+#define BOOTROM_NS_API_checked_flash_op 1
+#define BOOTROM_NS_API_flash_runtime_to_storage_addr 2
+#define BOOTROM_NS_API_get_partition_table_info 3
+#define BOOTROM_NS_API_secure_call 4
+#define BOOTROM_NS_API_otp_access 5
+#define BOOTROM_NS_API_reboot 6
+#define BOOTROM_NS_API_get_b_partition 7
+#define BOOTROM_NS_API_COUNT 8
+
+#define OTP_CMD_ROW_BITS 0x0000ffffu
+#define OTP_CMD_ROW_LSB _u(0)
+#define OTP_CMD_WRITE_BITS 0x00010000u
+#define OTP_CMD_WRITE_LSB _u(16)
+#define OTP_CMD_ECC_BITS 0x00020000u
+#define OTP_CMD_ECC_LSB _u(17)
+
+#ifndef __ASSEMBLER__
+static_assert(OTP_CMD_WRITE_BITS == (1 << OTP_CMD_WRITE_LSB), "");
+static_assert(OTP_CMD_ECC_BITS == (1 << OTP_CMD_ECC_LSB), "");
+
+typedef struct {
+ uint32_t permissions_and_location;
+ uint32_t permissions_and_flags;
+} resident_partition_t;
+static_assert(sizeof(resident_partition_t) == 8, "");
+
+typedef struct otp_cmd {
+ uint32_t flags;
+} otp_cmd_t;
+
+typedef enum {
+ BOOTROM_XIP_MODE_03H_SERIAL = 0,
+ BOOTROM_XIP_MODE_0BH_SERIAL,
+ BOOTROM_XIP_MODE_BBH_DUAL,
+ BOOTROM_XIP_MODE_EBH_QUAD,
+ BOOTROM_XIP_MODE_N_MODES
+} bootrom_xip_mode_t;
+
+// The checked flash API wraps the low-level flash routines from generic_flash, adding bounds
+// checking, permission checking against the resident partition table, and simple address
+// translation. The low-level API deals with flash offsets (i.e. distance from the start of the
+// first flash device, measured in bytes) but the checked flash API accepts one of two types of
+// address:
+//
+// - Flash runtime addresses: the address of some flash-resident data or code in the currently
+// running image. The flash addresses your binary is "linked at" by the linker.
+// - Flash storage addresses: a flash offset, plus the address base where QSPI hardware is first
+// mapped on the system bus (XIP_BASE constant from addressmap.h)
+//
+// These addresses are one and the same *if* the currently running program is stored at the
+// beginning of flash. They are different if the start of your image has been "rolled" by the flash
+// boot path to make it appear at the address it was linked at even though it is stored at a
+// different location in flash, which is necessary when you have A/B images for example.
+//
+// The address translation between flash runtime and flash storage addresses is configured in
+// hardware by the QMI_ATRANSx registers, and this API assumes those registers contain a valid
+// address mapping which it can use to translate runtime to storage addresses.
+
+typedef struct cflash_flags {
+ uint32_t flags;
+} cflash_flags_t;
+
+#endif // #ifdef __ASSEMBLER__
+
+// Bits which are permitted to be set in a flags variable -- any other bits being set is an error
+#define CFLASH_FLAGS_BITS 0x00070301u
+
+// Used to tell checked flash API which space a given address belongs to
+#define CFLASH_ASPACE_BITS 0x00000001u
+#define CFLASH_ASPACE_LSB _u(0)
+#define CFLASH_ASPACE_VALUE_STORAGE _u(0)
+#define CFLASH_ASPACE_VALUE_RUNTIME _u(1)
+
+// Used to tell checked flash APIs the effective security level of a flash access (may be forced to
+// one of these values for the NonSecure-exported version of this API)
+#define CFLASH_SECLEVEL_BITS 0x00000300u
+#define CFLASH_SECLEVEL_LSB _u(8)
+// Zero is not a valid security level:
+#define CFLASH_SECLEVEL_VALUE_SECURE _u(1)
+#define CFLASH_SECLEVEL_VALUE_NONSECURE _u(2)
+#define CFLASH_SECLEVEL_VALUE_BOOTLOADER _u(3)
+
+#define CFLASH_OP_BITS 0x00070000u
+#define CFLASH_OP_LSB _u(16)
+// Erase size_bytes bytes of flash, starting at address addr. Both addr and size_bytes must be a
+// multiple of 4096 bytes (one flash sector).
+#define CFLASH_OP_VALUE_ERASE _u(0)
+// Program size_bytes bytes of flash, starting at address addr. Both addr and size_bytes must be a
+// multiple of 256 bytes (one flash page).
+#define CFLASH_OP_VALUE_PROGRAM _u(1)
+// Read size_bytes bytes of flash, starting at address addr. There are no alignment restrictions on
+// addr or size_bytes.
+#define CFLASH_OP_VALUE_READ _u(2)
+#define CFLASH_OP_MAX _u(2)
+
+#endif
diff --git a/src/rp2_common/cmsis/CMakeLists.txt b/src/rp2_common/cmsis/CMakeLists.txt
index fa70ce430..fb1fea229 100644
--- a/src/rp2_common/cmsis/CMakeLists.txt
+++ b/src/rp2_common/cmsis/CMakeLists.txt
@@ -1,7 +1,7 @@
# Deferring this config until we decide how to include other CMSIS libraries... it is likely that we always want to use the stub version of the core
# at least if the vendor/device is RaspberryPi/RP2040...
-## PICO_CMAKE_CONFIG: PICO_CMSIS_PATH, directory to locate CMSIS installation, default="included stub CORE only impl", group=build
+## PICO_CMAKE_CONFIG: PICO_CMSIS_PATH, Directory to locate CMSIS installation, type=string, default="included stub CORE only impl", group=build
#if (DEFINED PICO_CMSIS_PATH)
# set(PICO_CMSIS_PATH "${PICO_CMSIS_PATH}" CACHE PATH "Path to the CMSIS tree to use with Raspberry Pi Pico SDK")
# message("Using specified PICO_CMSIS_PATH for CMSIS ('${PICO_CMSIS_PATH}')")
@@ -10,7 +10,7 @@
# message("Using PICO_CMSIS_PATH from environment for CMSIS ('${PICO_CMSIS_PATH}')")
#endif()
#
-## PICO_CMAKE_CONFIG: PICO_CMSIS_VENDOR, vendor name for CMSIS, default="RaspberryPi", group=build
+## PICO_CMAKE_CONFIG: PICO_CMSIS_VENDOR, Vendor name for CMSIS, type=string, default="RaspberryPi", group=build
#if (DEFINED PICO_CMSIS_VENDOR)
# set(PICO_CMSIS_VENDOR "${PICO_CMSIS_VENDOR}" CACHE STRING "CMSIS vendor name to use")
# message("Using specified PICO_CMSIS_VENDOR for CMSIS ('${PICO_CMSIS_VENDOR}')")
@@ -21,7 +21,7 @@
# set(PICO_CMSIS_VENDOR RaspberryPi)
#endif()
#
-## PICO_CMAKE_CONFIG: PICO_CMSIS_DEVICE, device name for CMSIS, default="RP2040", group=build
+## PICO_CMAKE_CONFIG: PICO_CMSIS_DEVICE, Device name for CMSIS, type=string, default="RP2040", group=build
#if (DEFINED PICO_CMSIS_DEVICE)
# set(PICO_CMSIS_DEVICE "${PICO_CMSIS_DEVICE}" CACHE STRING "CMSIS device name to use")
# message("Using specified PICO_CMSIS_DEVICE for CMSIS ('${PICO_CMSIS_DEVICE}')")
diff --git a/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h b/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h
index e825473da..0db37f4ca 100644
--- a/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h
+++ b/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h
@@ -55,50 +55,50 @@
#define isr_svcall SVC_Handler
#define isr_pendsv PendSV_Handler
#define isr_systick SysTick_Handler
-#define isr_irq0 TIMER0_IRQ_0_IRQn
-#define isr_irq1 TIMER0_IRQ_1_IRQn
-#define isr_irq2 TIMER0_IRQ_2_IRQn
-#define isr_irq3 TIMER0_IRQ_3_IRQn
-#define isr_irq4 TIMER1_IRQ_0_IRQn
-#define isr_irq5 TIMER1_IRQ_1_IRQn
-#define isr_irq6 TIMER1_IRQ_2_IRQn
-#define isr_irq7 TIMER1_IRQ_3_IRQn
-#define isr_irq8 PWM_IRQ_WRAP_0_IRQn
-#define isr_irq9 PWM_IRQ_WRAP_1_IRQn
-#define isr_irq10 DMA_IRQ_0_IRQn
-#define isr_irq11 DMA_IRQ_1_IRQn
-#define isr_irq12 DMA_IRQ_2_IRQn
-#define isr_irq13 DMA_IRQ_3_IRQn
-#define isr_irq14 USBCTRL_IRQ_IRQn
-#define isr_irq15 PIO0_IRQ_0_IRQn
-#define isr_irq16 PIO0_IRQ_1_IRQn
-#define isr_irq17 PIO1_IRQ_0_IRQn
-#define isr_irq18 PIO1_IRQ_1_IRQn
-#define isr_irq19 PIO2_IRQ_0_IRQn
-#define isr_irq20 PIO2_IRQ_1_IRQn
-#define isr_irq21 IO_IRQ_BANK0_IRQn
-#define isr_irq22 IO_IRQ_BANK0_NS_IRQn
-#define isr_irq23 IO_IRQ_QSPI_IRQn
-#define isr_irq24 IO_IRQ_QSPI_NS_IRQn
-#define isr_irq25 SIO_IRQ_FIFO_IRQn
-#define isr_irq26 SIO_IRQ_BELL_IRQn
-#define isr_irq27 SIO_IRQ_FIFO_NS_IRQn
-#define isr_irq28 SIO_IRQ_BELL_NS_IRQn
-#define isr_irq29 SIO_IRQ_MTIMECMP_IRQn
-#define isr_irq30 CLOCKS_IRQ_IRQn
-#define isr_irq31 SPI0_IRQ_IRQn
-#define isr_irq32 SPI1_IRQ_IRQn
-#define isr_irq33 UART0_IRQ_IRQn
-#define isr_irq34 UART1_IRQ_IRQn
-#define isr_irq35 ADC_IRQ_FIFO_IRQn
-#define isr_irq36 I2C0_IRQ_IRQn
-#define isr_irq37 I2C1_IRQ_IRQn
-#define isr_irq38 OTP_IRQ_IRQn
-#define isr_irq39 TRNG_IRQ_IRQn
-#define isr_irq42 PLL_SYS_IRQ_IRQn
-#define isr_irq43 PLL_USB_IRQ_IRQn
-#define isr_irq44 POWMAN_IRQ_POW_IRQn
-#define isr_irq45 POWMAN_IRQ_TIMER_IRQn
+#define isr_irq0 TIMER0_IRQ_0_Handler
+#define isr_irq1 TIMER0_IRQ_1_Handler
+#define isr_irq2 TIMER0_IRQ_2_Handler
+#define isr_irq3 TIMER0_IRQ_3_Handler
+#define isr_irq4 TIMER1_IRQ_0_Handler
+#define isr_irq5 TIMER1_IRQ_1_Handler
+#define isr_irq6 TIMER1_IRQ_2_Handler
+#define isr_irq7 TIMER1_IRQ_3_Handler
+#define isr_irq8 PWM_IRQ_WRAP_0_Handler
+#define isr_irq9 PWM_IRQ_WRAP_1_Handler
+#define isr_irq10 DMA_IRQ_0_Handler
+#define isr_irq11 DMA_IRQ_1_Handler
+#define isr_irq12 DMA_IRQ_2_Handler
+#define isr_irq13 DMA_IRQ_3_Handler
+#define isr_irq14 USBCTRL_IRQ_Handler
+#define isr_irq15 PIO0_IRQ_0_Handler
+#define isr_irq16 PIO0_IRQ_1_Handler
+#define isr_irq17 PIO1_IRQ_0_Handler
+#define isr_irq18 PIO1_IRQ_1_Handler
+#define isr_irq19 PIO2_IRQ_0_Handler
+#define isr_irq20 PIO2_IRQ_1_Handler
+#define isr_irq21 IO_IRQ_BANK0_Handler
+#define isr_irq22 IO_IRQ_BANK0_NS_Handler
+#define isr_irq23 IO_IRQ_QSPI_Handler
+#define isr_irq24 IO_IRQ_QSPI_NS_Handler
+#define isr_irq25 SIO_IRQ_FIFO_Handler
+#define isr_irq26 SIO_IRQ_BELL_Handler
+#define isr_irq27 SIO_IRQ_FIFO_NS_Handler
+#define isr_irq28 SIO_IRQ_BELL_NS_Handler
+#define isr_irq29 SIO_IRQ_MTIMECMP_Handler
+#define isr_irq30 CLOCKS_IRQ_Handler
+#define isr_irq31 SPI0_IRQ_Handler
+#define isr_irq32 SPI1_IRQ_Handler
+#define isr_irq33 UART0_IRQ_Handler
+#define isr_irq34 UART1_IRQ_Handler
+#define isr_irq35 ADC_IRQ_FIFO_Handler
+#define isr_irq36 I2C0_IRQ_Handler
+#define isr_irq37 I2C1_IRQ_Handler
+#define isr_irq38 OTP_IRQ_Handler
+#define isr_irq39 TRNG_IRQ_Handler
+#define isr_irq42 PLL_SYS_IRQ_Handler
+#define isr_irq43 PLL_USB_IRQ_Handler
+#define isr_irq44 POWMAN_IRQ_POW_Handler
+#define isr_irq45 POWMAN_IRQ_TIMER_Handler
#endif
#endif
diff --git a/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/system_RP2350.h b/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/system_RP2350.h
index 30881ccc6..d85fbeb6c 100644
--- a/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/system_RP2350.h
+++ b/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/system_RP2350.h
@@ -1,9 +1,9 @@
/*************************************************************************//**
- * @file system_RP2040.h
+ * @file system_RP2350.h
* @brief CMSIS-Core(M) Device Peripheral Access Layer Header File for
- * Device RP2040
- * @version V1.0.0
- * @date 5. May 2021
+ * Device RP2350
+ * @version V1.0.1
+ * @date 6. Sep 2024
*****************************************************************************/
/*
* Copyright (c) 2009-2021 Arm Limited. All rights reserved.
@@ -26,8 +26,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef _CMSIS_SYSTEM_RP2040_H
-#define _CMSIS_SYSTEM_RP2040_H
+#ifndef _CMSIS_SYSTEM_RP2350_H
+#define _CMSIS_SYSTEM_RP2350_H
#ifdef __cplusplus
extern "C" {
@@ -62,4 +62,4 @@ extern void SystemCoreClockUpdate (void);
}
#endif
-#endif /* _CMSIS_SYSTEM_RP2040_H */
+#endif /* _CMSIS_SYSTEM_RP2350_H */
diff --git a/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Source/system_RP2350.c b/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Source/system_RP2350.c
index 799d65a2b..3dc211346 100644
--- a/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Source/system_RP2350.c
+++ b/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Source/system_RP2350.c
@@ -1,9 +1,9 @@
/*************************************************************************//**
- * @file system_RP2040.c
+ * @file system_RP2350.c
* @brief CMSIS-Core(M) Device Peripheral Access Layer Header File for
- * Device RP2040
- * @version V1.0.0
- * @date 5. May 2021
+ * Device RP2350
+ * @version V1.0.1
+ * @date 6. Sep 2024
*****************************************************************************/
/*
* Copyright (c) 2009-2021 Arm Limited. All rights reserved.
@@ -49,4 +49,4 @@ void SystemCoreClockUpdate (void)
void __attribute__((constructor)) SystemInit (void)
{
SystemCoreClockUpdate();
-}
\ No newline at end of file
+}
diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h
index 5ca305570..20ab38a82 100644
--- a/src/rp2_common/hardware_adc/include/hardware/adc.h
+++ b/src/rp2_common/hardware_adc/include/hardware/adc.h
@@ -70,6 +70,11 @@
#define ADC_TEMPERATURE_CHANNEL_NUM (NUM_ADC_CHANNELS - 1)
#endif
+// PICO_CONFIG: PICO_ADC_CLKDIV_ROUND_NEAREST, True if floating point ADC clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_adc
+#ifndef PICO_ADC_CLKDIV_ROUND_NEAREST
+#define PICO_ADC_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -197,8 +202,12 @@ static inline void adc_run(bool run) {
* \param clkdiv If non-zero, conversion will be started at intervals rather than back to back.
*/
static inline void adc_set_clkdiv(float clkdiv) {
- invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1));
- adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB));
+ invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << REG_FIELD_WIDTH(ADC_DIV_INT));
+ const int frac_bit_count = REG_FIELD_WIDTH(ADC_DIV_FRAC);
+#if PICO_ADC_CLKDIV_ROUND_NEAREST
+ clkdiv += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
+#endif
+ adc_hw->div = (uint32_t)(clkdiv * (float) (1 << frac_bit_count));
}
/*! \brief Setup the ADC FIFO
diff --git a/src/rp2_common/hardware_boot_lock/BUILD.bazel b/src/rp2_common/hardware_boot_lock/BUILD.bazel
index 4f288dd59..96cb78270 100644
--- a/src/rp2_common/hardware_boot_lock/BUILD.bazel
+++ b/src/rp2_common/hardware_boot_lock/BUILD.bazel
@@ -8,6 +8,7 @@ cc_library(
hdrs = ["include/hardware/boot_lock.h"],
includes = ["include"],
tags = ["manual"],
+ deps = ["//src:pico_platform_internal"],
visibility = ["//src/rp2_common/pico_bootrom:__pkg__"],
)
diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c
index bcb6f9533..cf1b0f610 100644
--- a/src/rp2_common/hardware_clocks/clocks.c
+++ b/src/rp2_common/hardware_clocks/clocks.c
@@ -228,7 +228,7 @@ void clocks_enable_resus(resus_callback_t resus_callback) {
clocks_hw->resus.ctrl = CLOCKS_CLK_SYS_RESUS_CTRL_ENABLE_BITS | timeout;
}
-void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac) {
+void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t div_frac16) {
// Bit messy but it's as much code to loop through a lookup
// table. The sources for each gpout generators are the same
// so just call with the sources from GP0
@@ -245,10 +245,17 @@ void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div
invalid_params_if(HARDWARE_CLOCKS, true);
}
+ invalid_params_if(HARDWARE_CLOCKS, div_int >> REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_INT));
// Set up the gpclk generator
clocks_hw->clk[gpclk].ctrl = (src << CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_LSB) |
CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS;
- clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | div_frac;
+#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
+ clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | (div_frac16 << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB);
+#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
+ clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | ((div_frac16>>8u) << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB);
+#else
+#error unsupported number of fractional bits
+#endif
// Set gpio pin to gpclock function
gpio_set_function(gpio, GPIO_FUNC_GPCK);
@@ -342,13 +349,18 @@ void set_sys_clock_48mhz(void) {
}
}
-// PICO_CONFIG: PICO_CLOCK_AJDUST_PERI_CLOCK_WITH_SYS_CLOCK, When the SYS clock PLL is changed keep the peripheral clock attached to it, type=bool, default=0, advanced=true, group=hardware_clocks
-#ifndef PICO_CLOCK_AJDUST_PERI_CLOCK_WITH_SYS_CLOCK
+// PICO_CONFIG: PICO_CLOCK_ADJUST_PERI_CLOCK_WITH_SYS_CLOCK, When the SYS clock PLL is changed keep the peripheral clock attached to it, type=bool, default=0, advanced=true, group=hardware_clocks
+#ifndef PICO_CLOCK_ADJUST_PERI_CLOCK_WITH_SYS_CLOCK
+// support old incorrect spelling too
+#ifdef PICO_CLOCK_AJDUST_PERI_CLOCK_WITH_SYS_CLOCK
+#define PICO_CLOCK_ADJUST_PERI_CLOCK_WITH_SYS_CLOCK PICO_CLOCK_AJDUST_PERI_CLOCK_WITH_SYS_CLOCK
+#else
// By default, when reconfiguring the system clock PLL settings after runtime initialization,
// the peripheral clock is switched to the 48MHz USB clock to ensure continuity of peripheral operation.
// Setting this value to 1 changes the behavior to have the peripheral clock re-configured
// to the system clock at it's new frequency.
-#define PICO_CLOCK_AJDUST_PERI_CLOCK_WITH_SYS_CLOCK 0
+#define PICO_CLOCK_ADJUST_PERI_CLOCK_WITH_SYS_CLOCK 0
+#endif
#endif
void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2) {
@@ -374,7 +386,7 @@ void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2) {
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
freq);
-#if PICO_CLOCK_AJDUST_PERI_CLOCK_WITH_SYS_CLOCK
+#if PICO_CLOCK_ADJUST_PERI_CLOCK_WITH_SYS_CLOCK
clock_configure_undivided(clk_peri,
0,
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
@@ -427,4 +439,4 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u
}
}
return false;
-}
\ No newline at end of file
+}
diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h
index 511dafb1c..7611f80e8 100644
--- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h
+++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h
@@ -110,7 +110,7 @@ extern "C" {
* USB PLL | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB| CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
* ROSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_ROSC_CLKSRC | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
* XOSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
- * LPOSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_LPOSC_CLKSRC | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_LPOSC_CLKSRC | |
+ * LPOSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_LPOSC_CLKSRC | | |
* System clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_SYS | | |
* USB Clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_USB | | |
* ADC clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_ADC | | |
@@ -192,7 +192,7 @@ extern "C" {
#ifndef PLL_SYS_VCO_FREQ_HZ
#define PLL_SYS_VCO_FREQ_HZ (1500 * PICO_MHZ)
#endif
-// PICO_CONFIG: PLL_SYS_POSTDIV1, System clock PLL post divider 1 setting, type=int, default=6 on RP2040 5 or on RP2350, advanced=true, group=hardware_clocks
+// PICO_CONFIG: PLL_SYS_POSTDIV1, System clock PLL post divider 1 setting, type=int, default=6 on RP2040 or 5 on RP2350, advanced=true, group=hardware_clocks
#ifndef PLL_SYS_POSTDIV1
#if SYS_CLK_HZ == 125 * PICO_MHZ
#define PLL_SYS_POSTDIV1 6
@@ -253,6 +253,11 @@ extern "C" {
#else
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS 0
#endif
+#endif
+
+ // PICO_CONFIG: PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST, True if floating point GPIO clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_clocks
+#ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
+#define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
#endif
typedef clock_num_t clock_handle_t;
@@ -353,10 +358,29 @@ void clocks_enable_resus(resus_callback_t resus_callback);
*
* \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
* \param src The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
- * \param div_int The integer part of the value to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock. this is in range of 1..2^24-1.
- * \param div_frac The fractional part of the value to divide the source clock by. This is in range of 0..255 (/256).
+ * \param div_int The integer part of the value to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock. This is in range of 1..2^24-1 on RP2040
+ * and 1..2^16-1 on RP2350
+ * \param div_frac16 The fractional part of the value to divide the source clock by. This is in range of 0..65535 (/65536).
*/
-void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac);
+void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t div_frac16);
+
+/*! \brief Output an optionally divided clock to the specified gpio pin.
+ * \ingroup hardware_clocks
+ *
+ * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
+ * \param src The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
+ * \param div_int The integer part of the value to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock. This is in range of 1..2^24-1 on RP2040
+ * and 1..2^16-1 on RP2350
+ * \param div_frac8 The fractional part of the value to divide the source clock by. This is in range of 0..255 (/256).
+ */
+static inline void clock_gpio_init_int_frac8(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
+ return clock_gpio_init_int_frac16(gpio, src, div_int, (uint16_t)(div_frac8 << 8u));
+}
+
+// backwards compatibility
+static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
+ return clock_gpio_init_int_frac8(gpio, src, div_int, div_frac8);
+}
/*! \brief Output an optionally divided clock to the specified gpio pin.
* \ingroup hardware_clocks
@@ -368,8 +392,19 @@ void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div
static inline void clock_gpio_init(uint gpio, uint src, float div)
{
uint div_int = (uint)div;
- uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB));
- clock_gpio_init_int_frac(gpio, src, div_int, frac);
+ const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC);
+#if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
+ div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
+#endif
+#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
+ uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count));
+ clock_gpio_init_int_frac16(gpio, src, div_int, frac);
+#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
+ uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count));
+ clock_gpio_init_int_frac8(gpio, src, div_int, frac);
+#else
+#error unsupported number of fractional bits
+#endif
}
/*! \brief Configure a clock to come from a gpio input
@@ -383,14 +418,14 @@ static inline void clock_gpio_init(uint gpio, uint src, float div)
bool clock_configure_gpin(clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq);
/*! \brief Initialise the system clock to 48MHz
- * \ingroup pico_stdlib
+ * \ingroup hardware_clocks
*
* Set the system clock to 48MHz, and set the peripheral clock to match.
*/
void set_sys_clock_48mhz(void);
/*! \brief Initialise the system clock
- * \ingroup pico_stdlib
+ * \ingroup hardware_clocks
*
* \param vco_freq The voltage controller oscillator frequency to be used by the SYS PLL
* \param post_div1 The first post divider for the SYS PLL
@@ -401,7 +436,7 @@ void set_sys_clock_48mhz(void);
void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
/*! \brief Check if a given system clock frequency is valid/attainable
- * \ingroup pico_stdlib
+ * \ingroup hardware_clocks
*
* \param freq_hz Requested frequency
* \param vco_freq_out On success, the voltage controlled oscillator frequency to be used by the SYS PLL
@@ -412,7 +447,7 @@ void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
/*! \brief Check if a given system clock frequency is valid/attainable
- * \ingroup pico_stdlib
+ * \ingroup hardware_clocks
*
* \param freq_khz Requested frequency
* \param vco_freq_out On success, the voltage controlled oscillator frequency to be used by the SYS PLL
@@ -423,7 +458,7 @@ bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_ou
bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
/*! \brief Attempt to set a system clock frequency in hz
- * \ingroup pico_stdlib
+ * \ingroup hardware_clocks
*
* Note that not all clock frequencies are possible; it is preferred that you
* use src/rp2_common/hardware_clocks/scripts/vcocalc.py to calculate the parameters
@@ -445,7 +480,7 @@ static inline bool set_sys_clock_hz(uint32_t freq_hz, bool required) {
}
/*! \brief Attempt to set a system clock frequency in khz
- * \ingroup pico_stdlib
+ * \ingroup hardware_clocks
*
* Note that not all clock frequencies are possible; it is preferred that you
* use src/rp2_common/hardware_clocks/scripts/vcocalc.py to calculate the parameters
diff --git a/src/rp2_common/hardware_clocks/scripts/vcocalc.py b/src/rp2_common/hardware_clocks/scripts/vcocalc.py
index 08cca4126..775ffcdc9 100755
--- a/src/rp2_common/hardware_clocks/scripts/vcocalc.py
+++ b/src/rp2_common/hardware_clocks/scripts/vcocalc.py
@@ -62,6 +62,7 @@ def validRefdiv(string):
PLL_SYS_VCO_FREQ_HZ={int((args.input * 1_000_000) / best_refdiv * best_fbdiv)}
PLL_SYS_POSTDIV1={best_pd1}
PLL_SYS_POSTDIV2={best_pd2}
+ SYS_CLK_HZ={int((args.input * 1_000_000) / (best_refdiv * best_pd1 * best_pd2) * best_fbdiv)}
)
"""
if not args.cmake_only:
diff --git a/src/rp2_common/hardware_dma/dma.c b/src/rp2_common/hardware_dma/dma.c
index 5c405959f..9c0dab71b 100644
--- a/src/rp2_common/hardware_dma/dma.c
+++ b/src/rp2_common/hardware_dma/dma.c
@@ -75,8 +75,9 @@ void dma_channel_cleanup(uint channel) {
// Disable CHAIN_TO, and disable channel, so that it ignores any further triggers
hw_write_masked( &dma_hw->ch[channel].al1_ctrl, (channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB) | (0u << DMA_CH0_CTRL_TRIG_EN_LSB), DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS | DMA_CH0_CTRL_TRIG_EN_BITS );
// disable IRQs first as abort can cause spurious IRQs
- dma_channel_set_irq0_enabled(channel, false);
- dma_channel_set_irq1_enabled(channel, false);
+ for(uint i=0; i < NUM_DMA_IRQS; i++) {
+ dma_irqn_set_channel_enabled(i, channel, false);
+ }
dma_channel_abort(channel);
// finally clear the IRQ status, which may have been set during abort
dma_hw->intr = 1u << channel;
diff --git a/src/rp2_common/hardware_dma/include/hardware/dma.h b/src/rp2_common/hardware_dma/include/hardware/dma.h
index dd940ffc7..8bb35ec1f 100644
--- a/src/rp2_common/hardware_dma/include/hardware/dma.h
+++ b/src/rp2_common/hardware_dma/include/hardware/dma.h
@@ -911,7 +911,7 @@ static inline uint dma_get_timer_dreq(uint timer_num) {
* \ingroup hardware_dma
*
* \param irq_index 0 the DMA irq index
- * \return The \ref irq_num_to use for DMA
+ * \return The \ref irq_num_t to use for DMA
*/
static inline int dma_get_irq_num(uint irq_index) {
valid_params_if(HARDWARE_DMA, irq_index < NUM_DMA_IRQS);
diff --git a/src/rp2_common/hardware_exception/exception.c b/src/rp2_common/hardware_exception/exception.c
index 2c318e462..d3134fbc8 100644
--- a/src/rp2_common/hardware_exception/exception.c
+++ b/src/rp2_common/hardware_exception/exception.c
@@ -39,7 +39,7 @@ static void set_raw_exception_handler_and_restore_interrupts(enum exception_numb
}
static inline void check_exception_param(__unused enum exception_number num) {
- invalid_params_if(HARDWARE_EXCEPTION, num < MIN_EXCEPTION_NUM || num >= MAX_EXCEPTION_NUM);
+ invalid_params_if(HARDWARE_EXCEPTION, num < MIN_EXCEPTION_NUM || num > MAX_EXCEPTION_NUM);
}
exception_handler_t exception_get_vtable_handler(enum exception_number num) {
diff --git a/src/rp2_common/hardware_exception/include/hardware/exception.h b/src/rp2_common/hardware_exception/include/hardware/exception.h
index 377ec0156..d555c8cc4 100644
--- a/src/rp2_common/hardware_exception/include/hardware/exception.h
+++ b/src/rp2_common/hardware_exception/include/hardware/exception.h
@@ -39,13 +39,19 @@ extern "C" {
*
* On Arm these are vector table indices:
*
- * Name | Value | Exception
- * ---------------------|-------|-----------------------
- * NMI_EXCEPTION | 2 | Non Maskable Interrupt
- * HARDFAULT_EXCEPTION | 3 | HardFault
- * SVCALL_EXCEPTION | 11 | SV Call
- * PENDSV_EXCEPTION | 14 | Pend SV
- * SYSTICK_EXCEPTION | 15 | System Tick
+ * Name | Value | Exception
+ * ----------------------|-------|-----------------------
+ * NMI_EXCEPTION | 2 | Non Maskable Interrupt
+ * HARDFAULT_EXCEPTION | 3 | HardFault
+ * \if rp2350_specific
+ * MEMMANAGE_EXCEPTION | 4 | MemManage
+ * BUSFAULT_EXCEPTION | 5 | BusFault
+ * USAGEFAULT_EXCEPTION | 6 | UsageFault
+ * SECUREFAULT_EXCEPTION | 7 | SecureFault
+ * \endif
+ * SVCALL_EXCEPTION | 11 | SV Call
+ * PENDSV_EXCEPTION | 14 | Pend SV
+ * SYSTICK_EXCEPTION | 15 | System Tick
*
* \if rp2350_specific
* On RISC-V these are exception cause numbers:
@@ -88,11 +94,17 @@ enum exception_number {
enum exception_number {
// Assigned to VTOR indices
MIN_EXCEPTION_NUM = 2,
- NMI_EXCEPTION = 2, ///< Non Maskable Interrupt
- HARDFAULT_EXCEPTION = 3, ///< HardFault Interrupt
- SVCALL_EXCEPTION = 11, ///< SV Call Interrupt
- PENDSV_EXCEPTION = 14, ///< Pend SV Interrupt
- SYSTICK_EXCEPTION = 15, ///< System Tick Interrupt
+ NMI_EXCEPTION = 2, ///< Non Maskable Interrupt
+ HARDFAULT_EXCEPTION = 3, ///< HardFault Interrupt
+#if PICO_RP2350
+ MEMMANAGE_EXCEPTION = 4, ///< MemManage Interrupt
+ BUSFAULT_EXCEPTION = 5, ///< BusFault Interrupt
+ USAGEFAULT_EXCEPTION = 6, ///< UsageFault Interrupt
+ SECUREFAULT_EXCEPTION = 7, ///< SecureFault Interrupt
+#endif
+ SVCALL_EXCEPTION = 11, ///< SV Call Interrupt
+ PENDSV_EXCEPTION = 14, ///< Pend SV Interrupt
+ SYSTICK_EXCEPTION = 15, ///< System Tick Interrupt
MAX_EXCEPTION_NUM = 15
};
#endif
diff --git a/src/rp2_common/hardware_flash/BUILD.bazel b/src/rp2_common/hardware_flash/BUILD.bazel
index e443e261c..d50d0c73f 100644
--- a/src/rp2_common/hardware_flash/BUILD.bazel
+++ b/src/rp2_common/hardware_flash/BUILD.bazel
@@ -11,6 +11,7 @@ cc_library(
target_compatible_with = compatible_with_rp2(),
deps = [
"//src/rp2_common:hardware_structs",
+ "//src/rp2_common/hardware_xip_cache",
"//src/rp2_common:pico_platform",
"//src/rp2_common/pico_bootrom",
"//src/rp2_common/pico_multicore",
diff --git a/src/rp2_common/hardware_flash/CMakeLists.txt b/src/rp2_common/hardware_flash/CMakeLists.txt
index b0538ac1c..0139b9e4e 100644
--- a/src/rp2_common/hardware_flash/CMakeLists.txt
+++ b/src/rp2_common/hardware_flash/CMakeLists.txt
@@ -1,2 +1,3 @@
pico_simple_hardware_target(flash)
pico_mirrored_target_link_libraries(hardware_flash INTERFACE pico_bootrom)
+pico_mirrored_target_link_libraries(hardware_flash INTERFACE hardware_xip_cache)
diff --git a/src/rp2_common/hardware_flash/flash.c b/src/rp2_common/hardware_flash/flash.c
index 2116b0972..902d0daf7 100644
--- a/src/rp2_common/hardware_flash/flash.c
+++ b/src/rp2_common/hardware_flash/flash.c
@@ -12,14 +12,16 @@
#include "hardware/structs/ssi.h"
#else
#include "hardware/structs/qmi.h"
+#include "hardware/regs/otp_data.h"
#endif
+#include "hardware/xip_cache.h"
#define FLASH_BLOCK_ERASE_CMD 0xd8
// Standard RUID instruction: 4Bh command prefix, 32 dummy bits, 64 data bits.
#define FLASH_RUID_CMD 0x4b
#define FLASH_RUID_DUMMY_BYTES 4
-#define FLASH_RUID_DATA_BYTES 8
+#define FLASH_RUID_DATA_BYTES FLASH_UNIQUE_ID_SIZE_BYTES
#define FLASH_RUID_TOTAL_BYTES (1 + FLASH_RUID_DUMMY_BYTES + FLASH_RUID_DATA_BYTES)
//-----------------------------------------------------------------------------
@@ -69,6 +71,43 @@ static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
#endif
+#if PICO_RP2350
+// This is specifically for saving/restoring the registers modified by RP2350
+// flash_exit_xip() ROM func, not the entirety of the QMI window state.
+typedef struct flash_rp2350_qmi_save_state {
+ uint32_t timing;
+ uint32_t rcmd;
+ uint32_t rfmt;
+} flash_rp2350_qmi_save_state_t;
+
+static void __no_inline_not_in_flash_func(flash_rp2350_save_qmi_cs1)(flash_rp2350_qmi_save_state_t *state) {
+ state->timing = qmi_hw->m[1].timing;
+ state->rcmd = qmi_hw->m[1].rcmd;
+ state->rfmt = qmi_hw->m[1].rfmt;
+}
+
+static void __no_inline_not_in_flash_func(flash_rp2350_restore_qmi_cs1)(const flash_rp2350_qmi_save_state_t *state) {
+ if (flash_devinfo_get_cs_size(1) == FLASH_DEVINFO_SIZE_NONE) {
+ // Case 1: The RP2350 ROM sets QMI to a clean (03h read) configuration
+ // during flash_exit_xip(), even though when CS1 is not enabled via
+ // FLASH_DEVINFO it does not issue an XIP exit sequence to CS1. In
+ // this case, restore the original register config for CS1 as it is
+ // still the correct config.
+ qmi_hw->m[1].timing = state->timing;
+ qmi_hw->m[1].rcmd = state->rcmd;
+ qmi_hw->m[1].rfmt = state->rfmt;
+ } else {
+ // Case 2: If RAM is attached to CS1, and the ROM has issued an XIP
+ // exit sequence to it, then the ROM re-initialisation of the QMI
+ // registers has actually not gone far enough. The old XIP write mode
+ // is no longer valid when the QSPI RAM is returned to a serial
+ // command state. Restore the default 02h serial write command config.
+ qmi_hw->m[1].wfmt = QMI_M1_WFMT_RESET;
+ qmi_hw->m[1].wcmd = QMI_M1_WCMD_RESET;
+ }
+}
+#endif
+
//-----------------------------------------------------------------------------
// Actual flash programming shims (work whether or not PICO_NO_FLASH==1)
@@ -84,6 +123,12 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
assert(connect_internal_flash_func && flash_exit_xip_func && flash_range_erase_func && flash_flush_cache_func);
flash_init_boot2_copyout();
+ // Commit any pending writes to external RAM, to avoid losing them in the subsequent flush:
+ xip_cache_clean_all();
+#if PICO_RP2350
+ flash_rp2350_qmi_save_state_t qmi_save;
+ flash_rp2350_save_qmi_cs1(&qmi_save);
+#endif
// No flash accesses after this point
__compiler_memory_barrier();
@@ -93,6 +138,9 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
flash_range_erase_func(flash_offs, count, FLASH_BLOCK_SIZE, FLASH_BLOCK_ERASE_CMD);
flash_flush_cache_func(); // Note this is needed to remove CSn IO force as well as cache flushing
flash_enable_xip_via_boot2();
+#if PICO_RP2350
+ flash_rp2350_restore_qmi_cs1(&qmi_save);
+#endif
}
void __no_inline_not_in_flash_func(flash_flush_cache)(void) {
@@ -112,6 +160,11 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
assert(connect_internal_flash_func && flash_exit_xip_func && flash_range_program_func && flash_flush_cache_func);
flash_init_boot2_copyout();
+ xip_cache_clean_all();
+#if PICO_RP2350
+ flash_rp2350_qmi_save_state_t qmi_save;
+ flash_rp2350_save_qmi_cs1(&qmi_save);
+#endif
__compiler_memory_barrier();
@@ -120,6 +173,9 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
flash_range_program_func(flash_offs, data, count);
flash_flush_cache_func(); // Note this is needed to remove CSn IO force as well as cache flushing
flash_enable_xip_via_boot2();
+#if PICO_RP2350
+ flash_rp2350_restore_qmi_cs1(&qmi_save);
+#endif
}
//-----------------------------------------------------------------------------
@@ -152,6 +208,12 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
assert(connect_internal_flash_func && flash_exit_xip_func && flash_flush_cache_func);
flash_init_boot2_copyout();
+ xip_cache_clean_all();
+#if PICO_RP2350
+ flash_rp2350_qmi_save_state_t qmi_save;
+ flash_rp2350_save_qmi_cs1(&qmi_save);
+#endif
+
__compiler_memory_barrier();
connect_internal_flash_func();
flash_exit_xip_func();
@@ -198,6 +260,9 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
flash_flush_cache_func();
flash_enable_xip_via_boot2();
+#if PICO_RP2350
+ flash_rp2350_restore_qmi_cs1(&qmi_save);
+#endif
}
#endif
@@ -219,3 +284,89 @@ void flash_get_unique_id(uint8_t *id_out) {
id_out[i] = rxbuf[i + 1 + FLASH_RUID_DUMMY_BYTES];
#endif
}
+
+#if !PICO_RP2040
+// This is a static symbol because the layout of FLASH_DEVINFO is liable to change from device to
+// device, so fields must have getters/setters.
+static io_rw_16 * flash_devinfo_ptr(void) {
+ // Note the lookup returns a pointer to a 32-bit pointer literal in the ROM
+ io_rw_16 **p = (io_rw_16 **) rom_data_lookup(ROM_DATA_FLASH_DEVINFO16_PTR);
+ assert(p);
+ return *p;
+}
+
+static void flash_devinfo_update_field(uint16_t wdata, uint16_t mask) {
+ // Boot RAM does not support exclusives, but does support RWTYPE SET/CLR/XOR (with byte
+ // strobes). Can't use hw_write_masked because it performs a 32-bit write.
+ io_rw_16 *devinfo = flash_devinfo_ptr();
+ *hw_xor_alias(devinfo) = (*devinfo ^ wdata) & mask;
+}
+
+// This is a RAM function because may be called during flash programming to enable save/restore of
+// QMI window 1 registers on RP2350:
+flash_devinfo_size_t __no_inline_not_in_flash_func(flash_devinfo_get_cs_size)(uint cs) {
+ invalid_params_if(HARDWARE_FLASH, cs > 1);
+ io_ro_16 *devinfo = (io_ro_16 *) flash_devinfo_ptr();
+ if (cs == 0u) {
+#ifdef PICO_FLASH_SIZE_BYTES
+ // A flash size explicitly specified for the build (e.g. from the board header) takes
+ // precedence over whatever was found in OTP. Not using flash_devinfo_bytes_to_size() as
+ // the call could be outlined, and this code must be in RAM.
+ if (PICO_FLASH_SIZE_BYTES == 0) {
+ return FLASH_DEVINFO_SIZE_NONE;
+ } else {
+ return (flash_devinfo_size_t) (
+ __builtin_ctz(PICO_FLASH_SIZE_BYTES / 8192u) + (uint)FLASH_DEVINFO_SIZE_8K
+ );
+ }
+#else
+ return (flash_devinfo_size_t) (
+ (*devinfo & OTP_DATA_FLASH_DEVINFO_CS0_SIZE_BITS) >> OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB
+ );
+#endif
+ } else {
+ return (flash_devinfo_size_t) (
+ (*devinfo & OTP_DATA_FLASH_DEVINFO_CS1_SIZE_BITS) >> OTP_DATA_FLASH_DEVINFO_CS1_SIZE_LSB
+ );
+ }
+}
+
+void flash_devinfo_set_cs_size(uint cs, flash_devinfo_size_t size) {
+ invalid_params_if(HARDWARE_FLASH, cs > 1);
+ invalid_params_if(HARDWARE_FLASH, (uint)size > (uint)FLASH_DEVINFO_SIZE_MAX);
+ uint cs_shift = cs == 0u ? OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB : OTP_DATA_FLASH_DEVINFO_CS1_SIZE_LSB;
+ uint16_t cs_mask = OTP_DATA_FLASH_DEVINFO_CS0_SIZE_BITS >> OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB;
+ flash_devinfo_update_field(
+ (uint16_t)size << cs_shift,
+ cs_mask << cs_shift
+ );
+}
+
+bool flash_devinfo_get_d8h_erase_supported(void) {
+ return *flash_devinfo_ptr() & OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED_BITS;
+}
+
+void flash_devinfo_set_d8h_erase_supported(bool supported) {
+ flash_devinfo_update_field(
+ (uint)supported << OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED_LSB,
+ OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED_BITS
+ );
+}
+
+uint flash_devinfo_get_cs_gpio(uint cs) {
+ invalid_params_if(HARDWARE_FLASH, cs != 1);
+ (void)cs;
+ return (*flash_devinfo_ptr() & OTP_DATA_FLASH_DEVINFO_CS1_GPIO_BITS) >> OTP_DATA_FLASH_DEVINFO_CS1_GPIO_LSB;
+}
+
+void flash_devinfo_set_cs_gpio(uint cs, uint gpio) {
+ invalid_params_if(HARDWARE_FLASH, cs != 1);
+ invalid_params_if(HARDWARE_FLASH, gpio >= NUM_BANK0_GPIOS);
+ (void)cs;
+ flash_devinfo_update_field(
+ ((uint16_t)gpio) << OTP_DATA_FLASH_DEVINFO_CS1_GPIO_LSB,
+ OTP_DATA_FLASH_DEVINFO_CS1_GPIO_BITS
+ );
+}
+
+#endif // !PICO_RP2040
diff --git a/src/rp2_common/hardware_flash/include/hardware/flash.h b/src/rp2_common/hardware_flash/include/hardware/flash.h
index 87dafb15c..af6343274 100644
--- a/src/rp2_common/hardware_flash/include/hardware/flash.h
+++ b/src/rp2_common/hardware_flash/include/hardware/flash.h
@@ -14,10 +14,10 @@
*
* \brief Low level flash programming and erase API
*
- * Note these functions are *unsafe* if you are using both cores, and the other
- * is executing from flash concurrently with the operation. In this could be the
- * case, you must perform your own synchronisation to make sure that no XIP
- * accesses take place during flash programming. One option is to use the
+ * Note these functions are *unsafe* if you are using both cores, and the other
+ * is executing from flash concurrently with the operation. In this case, you
+ * must perform your own synchronisation to make sure that no XIP accesses take
+ * place during flash programming. One option is to use the
* \ref multicore_lockout functions.
*
* Likewise they are *unsafe* if you have interrupt handlers or an interrupt
@@ -46,7 +46,9 @@
#define FLASH_SECTOR_SIZE (1u << 12)
#define FLASH_BLOCK_SIZE (1u << 16)
+#ifndef FLASH_UNIQUE_ID_SIZE_BYTES
#define FLASH_UNIQUE_ID_SIZE_BYTES 8
+#endif
// PICO_CONFIG: PICO_FLASH_SIZE_BYTES, size of primary flash in bytes, type=int, default=Usually provided via board header, group=hardware_flash
@@ -119,6 +121,132 @@ void flash_do_cmd(const uint8_t *txbuf, uint8_t *rxbuf, size_t count);
void flash_flush_cache(void);
+#if !PICO_RP2040
+typedef enum {
+ FLASH_DEVINFO_SIZE_NONE = 0x0,
+ FLASH_DEVINFO_SIZE_8K = 0x1,
+ FLASH_DEVINFO_SIZE_16K = 0x2,
+ FLASH_DEVINFO_SIZE_32K = 0x3,
+ FLASH_DEVINFO_SIZE_64K = 0x4,
+ FLASH_DEVINFO_SIZE_128K = 0x5,
+ FLASH_DEVINFO_SIZE_256K = 0x6,
+ FLASH_DEVINFO_SIZE_512K = 0x7,
+ FLASH_DEVINFO_SIZE_1M = 0x8,
+ FLASH_DEVINFO_SIZE_2M = 0x9,
+ FLASH_DEVINFO_SIZE_4M = 0xa,
+ FLASH_DEVINFO_SIZE_8M = 0xb,
+ FLASH_DEVINFO_SIZE_16M = 0xc,
+ FLASH_DEVINFO_SIZE_MAX = 0xc
+} flash_devinfo_size_t;
+
+/*! \brief Convert a flash/PSRAM size enum to an integer size in bytes
+ * \ingroup hardware_flash
+ */
+static inline uint32_t flash_devinfo_size_to_bytes(flash_devinfo_size_t size) {
+ if (size == FLASH_DEVINFO_SIZE_NONE) {
+ return 0;
+ } else {
+ return 4096u << (uint)size;
+ }
+}
+
+/*! \brief Convert an integer flash/PSRAM size in bytes to a size enum, as
+ ! stored in OTP and used by the ROM.
+ * \ingroup hardware_flash
+ */
+static inline flash_devinfo_size_t flash_devinfo_bytes_to_size(uint32_t bytes) {
+ // Must be zero or a power of two
+ valid_params_if(HARDWARE_FLASH, (bytes & (bytes - 1)) == 0u);
+ uint sectors = bytes / 4096u;
+ if (sectors <= 1u) {
+ return FLASH_DEVINFO_SIZE_NONE;
+ } else {
+ return (flash_devinfo_size_t) __builtin_ctz(sectors);
+ }
+}
+
+/*! \brief Get the size of the QSPI device attached to chip select cs, according to FLASH_DEVINFO
+ * \ingroup hardware_flash
+ *
+ * \param cs Chip select index: 0 is QMI chip select 0 (QSPI CS pin), 1 is QMI chip select 1.
+ *
+ * The bootrom reads the FLASH_DEVINFO OTP data entry from OTP into boot RAM during startup. This
+ * contains basic information about the flash device which can be queried without communicating
+ * with the external device.(There are several methods to determine the size of a QSPI device over
+ * QSPI, but none are universally supported.)
+ *
+ * Since the FLASH_DEVINFO information is stored in boot RAM at runtime, it can be updated. Updates
+ * made in this way persist until the next reboot. The ROM uses this device information to control
+ * some low-level flash API behaviour, such as issuing an XIP exit sequence to CS 1 if its size is
+ * nonzero.
+ *
+ * If the macro PICO_FLASH_SIZE_BYTES is specified, this overrides the value for chip select 0. This
+ * can be specified in a board header if a board is always equipped with the same size of flash.
+ */
+flash_devinfo_size_t flash_devinfo_get_cs_size(uint cs);
+
+/*! \brief Update the size of the QSPI device attached to chip select cs in the runtime copy
+ * of FLASH_DEVINFO.
+ *
+ * \ingroup hardware_flash
+ *
+ * \param cs Chip select index: 0 is QMI chip select 0 (QSPI CS pin), 1 is QMI chip select 1.
+ *
+ * \param size The size of the attached device, or FLASH_DEVINFO_SIZE_NONE if there is none on this
+ * chip select.
+ *
+ * The bootrom maintains a copy in boot RAM of the FLASH_DEVINFO information read from OTP during
+ * startup. This function updates that copy to reflect runtime information about the sizes of
+ * attached QSPI devices.
+ *
+ * This controls the behaviour of some ROM flash APIs, such as bounds checking addresses for
+ * erase/programming in the checked_flash_op() API, or issuing an XIP exit sequence to CS 1 in
+ * flash_exit_xip() if the size is nonzero.
+ */
+void flash_devinfo_set_cs_size(uint cs, flash_devinfo_size_t size);
+
+/*! \brief Check whether all attached devices support D8h block erase with 64k size, according to
+ * FLASH_DEVINFO.
+ *
+ * \ingroup hardware_flash
+ *
+ * This controls whether checked_flash_op() ROM API uses D8h 64k block erase where possible, for
+ * faster erase times. If not, this ROM API always uses 20h 4k sector erase.
+ *
+ * The bootrom loads this flag from the OTP FLASH_DEVINFO data entry during startup, and stores it
+ * in boot RAM. You can update the boot RAM copy based on runtime knowledge of the attached QSPI
+ * devices.
+ */
+bool flash_devinfo_get_d8h_erase_supported(void);
+
+/*! \brief Specify whether all attached devices support D8h block erase with 64k size, in the
+ * runtime copy of FLASH_DEVINFO
+ *
+ * \ingroup hardware_flash
+ *
+ * This function updates the boot RAM copy of OTP FLASH_DEVINFO. The flag passed here is visible to
+ * ROM APIs, and is also returned in the next call to flash_devinfo_get_d8h_erase_supported()
+ */
+void flash_devinfo_set_d8h_erase_supported(bool supported);
+
+/*! \brief Check the GPIO allocated for each chip select, according to FLASH_DEVINFO
+ * \ingroup hardware_flash
+ *
+ * \param cs Chip select index (only the value 1 is supported on RP2350)
+ */
+uint flash_devinfo_get_cs_gpio(uint cs);
+
+/*! \brief Update the GPIO allocated for each chip select in the runtime copy of FLASH_DEVINFO
+ * \ingroup hardware_flash
+ *
+ * \param cs Chip select index (only the value 1 is supported on RP2350)
+ *
+ * \param gpio GPIO index (must be less than NUM_BANK0_GPIOS)
+ */
+void flash_devinfo_set_cs_gpio(uint cs, uint gpio);
+
+#endif // !PICO_RP2040
+
#ifdef __cplusplus
}
#endif
diff --git a/src/rp2_common/hardware_gpio/gpio.c b/src/rp2_common/hardware_gpio/gpio.c
index cb5fa869a..9dac191d9 100644
--- a/src/rp2_common/hardware_gpio/gpio.c
+++ b/src/rp2_common/hardware_gpio/gpio.c
@@ -192,7 +192,7 @@ void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) {
* The GPIO irq is managed by Zephyr, so there is no need to check it in the SDK.
*
assert(!enabled
- || (raw_irq_mask[get_core_num()] & (1u<> rs2[4:0]) & ~(-1 << nbits)
-
-.macro h3.bextm rd rs1 rs2 nbits
-.if (\nbits < 1) || (\nbits > 8)
-.err
-.endif
-#ifdef __hazard3_extension_xh3bextm
- .insn r 0x0b, 0x4, (((\nbits - 1) & 0x7 ) << 1), \rd, \rs1, \rs2
-#else
- srl \rd, \rs1, \rs2
- andi \rd, \rd, ((1 << \nbits) - 1)
-#endif
-.endm
-
-// h3.bextmi: Extract up to 8 consecutive bits from register rs1, with the
-// first bit index and the number of bits both configured by immediate
-// values. I-format instruction. Pseudocode:
-//
-// rd = (rs1 >> shamt) & ~(-1 << nbits)
-
-.macro h3.bextmi rd rs1 shamt nbits
-.if (\nbits < 1) || (\nbits > 8)
-.err
-.endif
-.if (\shamt < 0) || (\shamt > 31)
-.err
-.endif
-#ifdef __hazard3_extension_xh3bextm
- .insn i 0x0b, 0x4, \rd, \rs1, (\shamt & 0x1f) | (((\nbits - 1) & 0x7 ) << 6)
-#else
- srli \rd, \rs1, \shamt
- andi \rd, \rd, ((1 << \nbits) - 1)
-#endif
-.endm
-
-// h3.block: enter an idle state until another processor in the same
-// multiprocessor complex executes an h3.unblock instruction, or the
-// processor is interrupted. Fall through immediately if an h3.unblock has
-// been received since the last execution of an h3.block on this processor.
-// On RP2350, processors also have their own h3.unblock signals reflected
-// back to them.
-
-.macro h3.block
-#ifdef __hazard3_extension_xh3power
- slt x0, x0, x0
-#else
- nop
-#endif
-.endm
-
-// h3.unblock: signal other processors in the same multiprocessor complex to
-// exit the idle state entered by an h3.block instruction. On RP2350, this
-// signal is also reflected back to the processor that executed the
-// h3.unblock, which will cause that processor's next h3.block to fall
-// through immediately.
-
-.macro h3.unblock
-#ifdef __hazard3_extension_xh3power
- slt x0, x0, x1
-#else
- nop
-#endif
-.endm
-
-#else // !__ASSEMBLER__
+#ifndef __ASSEMBLER__
#ifdef __cplusplus
extern "C" {
@@ -128,51 +53,10 @@ extern "C" {
#define hazard3_irqarray_clear(csr, index, data) static_assert(false, "Not supported: Xh3irq extension")
#endif
-
-// nbits must be a constant expression
-#ifdef __hazard3_extension_xh3bextm
-#define __hazard3_bextm(nbits, rs1, rs2) ({\
- uint32_t __h3_bextm_rd; \
- asm (".insn r 0x0b, 0, %3, %0, %1, %2"\
- : "=r" (__h3_bextm_rd) \
- : "r" (rs1), "r" (rs2), "i" ((((nbits) - 1) & 0x7) << 1)\
- ); \
- __h3_bextm_rd; \
-})
-#else
-#define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((rs2) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
-#endif
-
-// nbits and shamt must be constant expressions
-#ifdef __hazard3_extension_xh3bextm
-#define __hazard3_bextmi(nbits, rs1, shamt) ({\
- uint32_t __h3_bextmi_rd; \
- asm (".insn i 0x0b, 0x4, %0, %1, %2"\
- : "=r" (__h3_bextmi_rd) \
- : "r" (rs1), "i" ((((nbits) - 1) & 0x7) << 6 | ((shamt) & 0x1f)) \
- ); \
- __h3_bextmi_rd; \
-})
-#else
-#define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((shamt) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
-#endif
-
-#ifdef __hazard3_extension_xh3power
-#define __hazard3_block() asm volatile ("slt x0, x0, x0" : : : "memory")
-#else
-#define __hazard3_block() do {} while (0)
-#endif
-
-#ifdef __hazard3_extension_xh3power
-#define __hazard3_unblock() asm volatile ("slt x0, x0, x1" : : : "memory")
-#else
-#define __hazard3_unblock() do {} while (0)
-#endif
-
#ifdef __cplusplus
}
#endif
-#endif // !__ASSEMBLER__
+#endif
#endif
diff --git a/src/rp2_common/hardware_hazard3/include/hardware/hazard3/features.h b/src/rp2_common/hardware_hazard3/include/hardware/hazard3/features.h
new file mode 100644
index 000000000..25e5d2fba
--- /dev/null
+++ b/src/rp2_common/hardware_hazard3/include/hardware/hazard3/features.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_HAZARD3_FEATURES_H
+#define _HARDWARE_HAZARD3_FEATURES_H
+
+#include "pico.h"
+
+/** \file hardware/hazard3/features.h
+ * \addtogroup hardware_hazard3
+ *
+ * \brief Sets macros for supported Hazard3 custom extensions (features) based on PICO_PLATFORM macros
+ *
+ */
+
+// Feature detection macros for Hazard3 custom extensions
+#if PICO_RP2350
+// Version 1.0 of these four extensions
+// (encoded as major * 100 + minor)
+#define __hazard3_extension_xh3power 100
+#define __hazard3_extension_xh3bextm 100
+#define __hazard3_extension_xh3irq 100
+#define __hazard3_extension_xh3pmpm 100
+#endif
+
+#endif
diff --git a/src/rp2_common/hardware_hazard3/include/hardware/hazard3/instructions.h b/src/rp2_common/hardware_hazard3/include/hardware/hazard3/instructions.h
new file mode 100644
index 000000000..7abeb5ba6
--- /dev/null
+++ b/src/rp2_common/hardware_hazard3/include/hardware/hazard3/instructions.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_HAZARD3_INSTRUCTIONS_H
+#define _HARDWARE_HAZARD3_INSTRUCTIONS_H
+
+#include "pico.h"
+
+// Get list of supported extensions based on platform:
+#include "hardware/hazard3/features.h"
+
+/** \file hardware/hazard3/instructions.h
+ * \addtogroup hardware_hazard3
+ *
+ * \brief Intrinsics and asm macros for Hazard3 custom instructions
+ *
+ * The implementation of these intrinsics depends on the feature macros
+ * defined in hardware/hazard3/features.h. When the relevant feature is not
+ * present, the intrinsics fall back on an RV32I equivalent if possible.
+ *
+ */
+
+#ifdef __ASSEMBLER__
+
+// Assembly language instruction macros for Hazard3 custom instructions
+
+// h3.bextm: Extract up to 8 consecutive bits from register rs1, with the
+// first bit indexed by rs2, and bit count configured by an immediate value.
+// R-format instruction. Pseudocode:
+//
+// rd = (rs1 >> rs2[4:0]) & ~(-1 << nbits)
+
+.macro h3.bextm rd rs1 rs2 nbits
+.if (\nbits < 1) || (\nbits > 8)
+.err
+.endif
+#ifdef __hazard3_extension_xh3bextm
+ .insn r 0x0b, 0x4, (((\nbits - 1) & 0x7 ) << 1), \rd, \rs1, \rs2
+#else
+ srl \rd, \rs1, \rs2
+ andi \rd, \rd, ((1 << \nbits) - 1)
+#endif
+.endm
+
+// h3.bextmi: Extract up to 8 consecutive bits from register rs1, with the
+// first bit index and the number of bits both configured by immediate
+// values. I-format instruction. Pseudocode:
+//
+// rd = (rs1 >> shamt) & ~(-1 << nbits)
+
+.macro h3.bextmi rd rs1 shamt nbits
+.if (\nbits < 1) || (\nbits > 8)
+.err
+.endif
+.if (\shamt < 0) || (\shamt > 31)
+.err
+.endif
+#ifdef __hazard3_extension_xh3bextm
+ .insn i 0x0b, 0x4, \rd, \rs1, (\shamt & 0x1f) | (((\nbits - 1) & 0x7 ) << 6)
+#else
+ srli \rd, \rs1, \shamt
+ andi \rd, \rd, ((1 << \nbits) - 1)
+#endif
+.endm
+
+// h3.block: enter an idle state until another processor in the same
+// multiprocessor complex executes an h3.unblock instruction, or the
+// processor is interrupted. Fall through immediately if an h3.unblock has
+// been received since the last execution of an h3.block on this processor.
+// On RP2350, processors also have their own h3.unblock signals reflected
+// back to them.
+
+.macro h3.block
+#ifdef __hazard3_extension_xh3power
+ slt x0, x0, x0
+#else
+ nop
+#endif
+.endm
+
+// h3.unblock: signal other processors in the same multiprocessor complex to
+// exit the idle state entered by an h3.block instruction. On RP2350, this
+// signal is also reflected back to the processor that executed the
+// h3.unblock, which will cause that processor's next h3.block to fall
+// through immediately.
+
+.macro h3.unblock
+#ifdef __hazard3_extension_xh3power
+ slt x0, x0, x1
+#else
+ nop
+#endif
+.endm
+
+#else // !__ASSEMBLER__
+
+// C language instruction macros for Hazard3 custom instructions
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// nbits must be a constant expression
+#ifdef __hazard3_extension_xh3bextm
+#define __hazard3_bextm(nbits, rs1, rs2) ({\
+ uint32_t __h3_bextm_rd; \
+ asm (".insn r 0x0b, 0, %3, %0, %1, %2"\
+ : "=r" (__h3_bextm_rd) \
+ : "r" (rs1), "r" (rs2), "i" ((((nbits) - 1) & 0x7) << 1)\
+ ); \
+ __h3_bextm_rd; \
+})
+#else
+#define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((rs2) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
+#endif
+
+// nbits and shamt must be constant expressions
+#ifdef __hazard3_extension_xh3bextm
+#define __hazard3_bextmi(nbits, rs1, shamt) ({\
+ uint32_t __h3_bextmi_rd; \
+ asm (".insn i 0x0b, 0x4, %0, %1, %2"\
+ : "=r" (__h3_bextmi_rd) \
+ : "r" (rs1), "i" ((((nbits) - 1) & 0x7) << 6 | ((shamt) & 0x1f)) \
+ ); \
+ __h3_bextmi_rd; \
+})
+#else
+#define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((shamt) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
+#endif
+
+#ifdef __hazard3_extension_xh3power
+#define __hazard3_block() asm volatile ("slt x0, x0, x0" : : : "memory")
+#else
+#define __hazard3_block() do {} while (0)
+#endif
+
+#ifdef __hazard3_extension_xh3power
+#define __hazard3_unblock() asm volatile ("slt x0, x0, x1" : : : "memory")
+#else
+#define __hazard3_unblock() do {} while (0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !__ASSEMBLER__
+
+#endif
diff --git a/src/rp2_common/hardware_i2c/i2c.c b/src/rp2_common/hardware_i2c/i2c.c
index 865c16f3b..e6fc76419 100644
--- a/src/rp2_common/hardware_i2c/i2c.c
+++ b/src/rp2_common/hardware_i2c/i2c.c
@@ -259,6 +259,12 @@ int i2c_write_timeout_per_char_us(i2c_inst_t *i2c, uint8_t addr, const uint8_t *
init_per_iteration_timeout_us(&ts, timeout_per_char_us), &ts);
}
+int i2c_write_burst_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len) {
+ int rc = i2c_write_blocking_internal(i2c, addr, src, len, true, NULL, NULL);
+ i2c->restart_on_next = false;
+ return rc;
+}
+
static int i2c_read_blocking_internal(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len, bool nostop,
check_timeout_fn timeout_check, timeout_state_t *ts) {
invalid_params_if(HARDWARE_I2C, addr >= 0x80); // 7-bit addresses
@@ -292,7 +298,10 @@ static int i2c_read_blocking_internal(i2c_inst_t *i2c, uint8_t addr, uint8_t *ds
do {
abort_reason = i2c->hw->tx_abrt_source;
- abort = (bool) i2c->hw->clr_tx_abrt;
+ if (i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS) {
+ abort = true;
+ i2c->hw->clr_tx_abrt;
+ }
if (timeout_check) {
timeout = timeout_check(ts, false);
abort |= timeout;
@@ -341,3 +350,9 @@ int i2c_read_timeout_per_char_us(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, si
return i2c_read_blocking_internal(i2c, addr, dst, len, nostop,
init_per_iteration_timeout_us(&ts, timeout_per_char_us), &ts);
}
+
+int i2c_read_burst_blocking(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len) {
+ int rc = i2c_read_blocking_internal(i2c, addr, dst, len, true, NULL, NULL);
+ i2c->restart_on_next = false;
+ return rc;
+}
diff --git a/src/rp2_common/hardware_i2c/include/hardware/i2c.h b/src/rp2_common/hardware_i2c/include/hardware/i2c.h
index 13bafcc2d..604b89f98 100644
--- a/src/rp2_common/hardware_i2c/include/hardware/i2c.h
+++ b/src/rp2_common/hardware_i2c/include/hardware/i2c.h
@@ -55,8 +55,8 @@ extern "C" {
typedef struct i2c_inst i2c_inst_t;
// PICO_CONFIG: PICO_DEFAULT_I2C, Define the default I2C for a board, min=0, max=1, default=Usually provided via board header, group=hardware_i2c
-// PICO_CONFIG: PICO_DEFAULT_I2C_SDA_PIN, Define the default I2C SDA pin, min=0, max=29, default=Usually provided via board header, group=hardware_i2c
-// PICO_CONFIG: PICO_DEFAULT_I2C_SCL_PIN, Define the default I2C SCL pin, min=0, max=29, default=Usually provided via board header, group=hardware_i2c
+// PICO_CONFIG: PICO_DEFAULT_I2C_SDA_PIN, Define the default I2C SDA pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_i2c
+// PICO_CONFIG: PICO_DEFAULT_I2C_SCL_PIN, Define the default I2C SCL pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_i2c
/** The I2C identifiers for use in I2C functions.
*
@@ -316,6 +316,21 @@ int i2c_read_timeout_per_char_us(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, si
*/
int i2c_write_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, bool nostop);
+/*! \brief Attempt to write specified number of bytes to address, blocking in burst mode
+ * \ingroup hardware_i2c
+ *
+ * This version of the function will not issue a stop and will not restart on the next write.
+ * This allows you to write consecutive bytes of data without having to resend a stop bit and
+ * (for example) without having to send address byte(s) repeatedly
+ *
+ * \param i2c Either \ref i2c0 or \ref i2c1
+ * \param addr 7-bit address of device to read from
+ * \param dst Pointer to buffer to receive data
+ * \param len Length of data in bytes to receive
+ * \return Number of bytes read, or PICO_ERROR_GENERIC if address not acknowledged or no device present.
+ */
+int i2c_write_burst_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len);
+
/*! \brief Attempt to read specified number of bytes from address, blocking
* \ingroup hardware_i2c
*
@@ -329,6 +344,20 @@ int i2c_write_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t
*/
int i2c_read_blocking(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len, bool nostop);
+/*! \brief Attempt to read specified number of bytes from address, blocking in burst mode
+ * \ingroup hardware_i2c
+ *
+ * This version of the function will not issue a stop and will not restart on the next read.
+ * This allows you to read consecutive bytes of data without having to resend a stop bit and
+ * (for example) without having to send address byte(s) repeatedly
+ *
+ * \param i2c Either \ref i2c0 or \ref i2c1
+ * \param addr 7-bit address of device to read from
+ * \param dst Pointer to buffer to receive data
+ * \param len Length of data in bytes to receive
+ * \return Number of bytes read, or PICO_ERROR_GENERIC if address not acknowledged or no device present.
+ */
+int i2c_read_burst_blocking(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len);
/*! \brief Determine non-blocking write space available
* \ingroup hardware_i2c
diff --git a/src/rp2_common/hardware_interp/include/hardware/interp.h b/src/rp2_common/hardware_interp/include/hardware/interp.h
index edf541c8a..634af0f46 100644
--- a/src/rp2_common/hardware_interp/include/hardware/interp.h
+++ b/src/rp2_common/hardware_interp/include/hardware/interp.h
@@ -438,9 +438,11 @@ static inline uint32_t interp_peek_full_result(interp_hw_t *interp) {
* \param lane The lane number, 0 or 1
* \param val Value to add
*/
-static inline void interp_add_accumulater(interp_hw_t *interp, uint lane, uint32_t val) {
+static inline void interp_add_accumulator(interp_hw_t *interp, uint lane, uint32_t val) {
interp->add_raw[lane] = val;
}
+// backwards incompatibility with old incorrect spelling
+#define interp_add_accumulater(interp, lane, val) interp_add_accumulator(interp, lane, val)
/*! \brief Get raw lane value
* \ingroup hardware_interp
diff --git a/src/rp2_common/hardware_irq/CMakeLists.txt b/src/rp2_common/hardware_irq/CMakeLists.txt
index 4795f85ff..e64a0ec38 100644
--- a/src/rp2_common/hardware_irq/CMakeLists.txt
+++ b/src/rp2_common/hardware_irq/CMakeLists.txt
@@ -4,7 +4,8 @@ pico_simple_hardware_target(irq)
target_sources(hardware_irq INTERFACE ${CMAKE_CURRENT_LIST_DIR}/irq_handler_chain.S)
-target_link_libraries(hardware_irq INTERFACE pico_sync) # not mirrored as only implementation requires it
+# irq.c includes pico/runtime_init.h
+target_link_libraries(hardware_irq INTERFACE pico_sync pico_runtime_init_headers) # not mirrored as only implementation requires it
if (PICO_RISCV)
pico_mirrored_target_link_libraries(hardware_irq INTERFACE hardware_hazard3)
endif()
diff --git a/src/rp2_common/hardware_irq/include/hardware/irq.h b/src/rp2_common/hardware_irq/include/hardware/irq.h
index eeb4fc474..b4d41de71 100644
--- a/src/rp2_common/hardware_irq/include/hardware/irq.h
+++ b/src/rp2_common/hardware_irq/include/hardware/irq.h
@@ -18,7 +18,7 @@
#define PICO_DISABLE_SHARED_IRQ_HANDLERS 0
#endif
-// PICO_CONFIG: PICO_VTABLE_PER_CORE, user is using separate vector tables per core, type=bool, default=0, group=hardware_irq
+// PICO_CONFIG: PICO_VTABLE_PER_CORE, User is using separate vector tables per core, type=bool, default=0, group=hardware_irq
#ifndef PICO_VTABLE_PER_CORE
#define PICO_VTABLE_PER_CORE 0
#endif
diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h
index 7eda36da6..7ca20d64c 100644
--- a/src/rp2_common/hardware_pio/include/hardware/pio.h
+++ b/src/rp2_common/hardware_pio/include/hardware/pio.h
@@ -23,7 +23,7 @@
#endif
#endif
-// PICO_CONFIG: PICO_PIO_VERSION, The PIO hardware version, type=int, default=0 on RP2040 and 1 on RP2350, group=hardware_pio
+// PICO_CONFIG: PICO_PIO_VERSION, PIO hardware version, type=int, default=0 on RP2040 and 1 on RP2350, group=hardware_pio
#ifndef PICO_PIO_VERSION
#if PIO_GPIOBASE_BITS
#define PICO_PIO_VERSION 1
@@ -31,6 +31,12 @@
#define PICO_PIO_VERSION 0
#endif
#endif
+
+// PICO_CONFIG: PICO_PIO_CLKDIV_ROUND_NEAREST, True if floating point PIO clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_pio
+#ifndef PICO_PIO_CLKDIV_ROUND_NEAREST
+#define PICO_PIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
+#endif
+
/** \file hardware/pio.h
* \defgroup hardware_pio hardware_pio
*
@@ -63,6 +69,31 @@
* Full details of the PIO can be found in the appropriate RP-series datasheet. Note that there are
* additional features in the RP2350 PIO implementation that mean care should be taken when writing PIO
* code that needs to run on both the RP2040 and the RP2350.
+ *
+ * \anchor pio_sm_pins
+ * \if rp2040_specific
+ * On RP2040, pin numbers may always be specified from 0-31
+ * \endif
+ *
+ * \if rp2350_specific
+ * On RP2350A, pin numbers may always be specified from 0-31.
+ *
+ * On RP2350B, there are 48 pins but each PIO instance can only address 32 pins (the PIO
+ * instance either addresses pins 0-31 or 16-47 based on \ref pio_set_gpio_base). The
+ * `pio_sm_` methods that directly affect the hardware always take _real_ pin numbers in the full range, however:
+ *
+ * * If `PICO_PIO_USE_GPIO_BASE != 1` then the 5th bit of the pin number is ignored. This is done so
+ * that programs compiled for boards with RP2350A do not incur the extra overhead of dealing with higher pins that don't exist.
+ * Effectively these functions behave exactly like RP2040 in this case.
+ * Note that `PICO_PIO_USE_GPIO_BASE` is defaulted to 0 if `PICO_RP2350A` is 1
+ * * If `PICO_PIO_USE_GPIO_BASE == 1` then the passed pin numbers are adjusted internally by subtracting
+ * the GPIO base to give a pin number in the range 0-31 from the PIO's perspective
+ *
+ * You can set `PARAM_ASSERTIONS_ENABLED_HARDWARE_PIO = 1` to enable parameter checking to debug pin (or other) issues with
+ * hardware_pio methods.
+ *
+ * Note that pin masks follow the same rules as individual pins; bit N of a 32-bit or 64-bit mask always refers to pin N.
+ * \endif
*/
#ifdef __cplusplus
@@ -115,9 +146,9 @@ typedef pio_hw_t *PIO;
#define pio1 pio1_hw
#if NUM_PIOS > 2
-/** Identifier for the second (PIO 1) hardware PIO instance (for use in PIO functions).
+/** Identifier for the third (PIO 2) hardware PIO instance (for use in PIO functions).
*
- * e.g. pio_gpio_init(pio1, 5)
+ * e.g. pio_gpio_init(pio2, 5)
*
* \ingroup hardware_pio
*/
@@ -206,6 +237,37 @@ static_assert(DREQ_PIO1_RX0 == DREQ_PIO1_TX0 + NUM_PIO_STATE_MACHINES, "");
* A PIO block needs to be configured, these functions provide helpers to set up configuration
* structures. See \ref pio_sm_set_config
*
+ * \anchor sm_config_pins
+ * \if rp2040_specific
+ * On RP2040, pin numbers may always be specified from 0-31
+ * \endif
+ *
+ * \if rp2350_specific
+ * On RP2350A, pin numbers may always be specified from 0-31.
+ *
+ * On RP2350B, there are 48 pins but each PIO instance can only address 32 pins (the PIO
+ * instance either addresses pins 0-31 or 16-47 based on \ref pio_set_gpio_base). The
+ * `sm_config_` state machine configuration always take _real_ pin numbers in the full range, however:
+ *
+ * * If `PICO_PIO_USE_GPIO_BASE != 1` then the 5th bit of the pin number is ignored. This is done so
+ * that programs compiled for boards with RP2350A do not incur the extra overhead of dealing with higher pins that don't exist.
+ * Effectively these functions behave exactly like RP2040 in this case.
+ * Note that `PICO_PIO_USE_GPIO_BASE` is defaulted to 0 if `PICO_RP2350A` is 1
+ * * If `PICO_PIO_USE_GPIO_BASE == 1` then the state machine configuration stores the actual pin numbers in the range 0-47.
+ * Of course in this scenario, it is possible to make an invalid configuration (one which uses pins in both the ranges
+ * 0-15 and 32-47).
+ *
+ * \ref pio_sm_set_config (or \ref pio_sm_init which calls it) attempts to apply the configuration to a particular PIO's state machine,
+ * and will return PICO_ERROR_BAD_ALIGNMENT if the configuration cannot be applied due to the above problem,
+ * or if the PIO's GPIO base (see \ref pio_set_gpio_base) does not allow access to the required pins.
+ *
+ * To be clear, \ref pio_sm_set_config does not change the PIO's GPIO base for you; you must configre the PIO's
+ * GPIO base before calling the method, however you can use \ref pio_claim_free_sm_and_add_program_for_gpio_range
+ * to find/configure a PIO instance suitable for a partiular GPIO range.
+ *
+ * You can set `PARAM_ASSERTIONS_ENABLED_HARDWARE_PIO = 1` to enable parameter checking to debug pin (or other) issues with
+ * hardware_pio methods.
+ * \endif
*/
/** \brief PIO Configuration structure
@@ -222,9 +284,10 @@ typedef struct {
#if PICO_PIO_USE_GPIO_BASE
#define PINHI_ALL_PINCTRL_LSBS ((1u << PIO_SM0_PINCTRL_IN_BASE_LSB) | (1u << PIO_SM0_PINCTRL_OUT_BASE_LSB) | \
(1u << PIO_SM0_PINCTRL_SET_BASE_LSB) | (1u << PIO_SM0_PINCTRL_SIDESET_BASE_LSB))
-static_assert( 0 == (0xff000000u & (PINHI_ALL_PINCTRL_LSBS * 0x1f)), "");
-// note we put the jmp_ctrl pin starting at bit 24
-#define PINHI_ALL_PIN_LSBS ((1u << 24) | (1u << PIO_SM0_PINCTRL_IN_BASE_LSB) | (1u << PIO_SM0_PINCTRL_OUT_BASE_LSB) | \
+// note we put the out_special pin starting at bit 20
+#define PINHI_EXECCTRL_LSB 20
+static_assert( (1u << PINHI_EXECCTRL_LSB) > (PINHI_ALL_PINCTRL_LSBS * 0x1f), "");
+#define PINHI_ALL_PIN_LSBS ((1u << PINHI_EXECCTRL_LSB) |(1u << PIO_SM0_PINCTRL_IN_BASE_LSB) | (1u << PIO_SM0_PINCTRL_OUT_BASE_LSB) | \
(1u << PIO_SM0_PINCTRL_SET_BASE_LSB) | (1u << PIO_SM0_PINCTRL_SIDESET_BASE_LSB))
// each 5-bit field which would usually be used for the pin_base in pin_ctrl, is used for:
// 0b11111 - corresponding field not specified
@@ -266,7 +329,7 @@ static inline void check_pio_pin_param(__unused uint pin) {
* 'out' pins can overlap with the 'in', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
- * \param out_base 0-31 First pin to set as output
+ * \param out_base First pin to set as output. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_out_pin_base(pio_sm_config *c, uint out_base) {
check_pio_pin_param(out_base);
@@ -298,7 +361,7 @@ static inline void sm_config_set_out_pin_count(pio_sm_config *c, uint out_count)
* 'out' pins can overlap with the 'in', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
- * \param out_base 0-31 First pin to set as output
+ * \param out_base First pin to set as output. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
* \param out_count 0-32 Number of pins to set.
*/
static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint out_count) {
@@ -312,7 +375,7 @@ static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint
* 'set' pins can overlap with the 'in', 'out' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
- * \param set_base 0-31 First pin to set as
+ * \param set_base First pin to use as 'set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_set_pin_base(pio_sm_config *c, uint set_base) {
check_pio_pin_param(set_base);
@@ -344,7 +407,7 @@ static inline void sm_config_set_set_pin_count(pio_sm_config *c, uint set_count)
* 'set' pins can overlap with the 'in', 'out' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
- * \param set_base 0-31 First pin to set as
+ * \param set_base First pin to use as 'set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
* \param set_count 0-5 Number of pins to set.
*/
static inline void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint set_count) {
@@ -358,7 +421,7 @@ static inline void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint
* 'in' pins can overlap with the 'out', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
- * \param in_base 0-31 First pin to use as input
+ * \param in_base First pin to use as input. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_in_pin_base(pio_sm_config *c, uint in_base) {
check_pio_pin_param(in_base);
@@ -370,18 +433,31 @@ static inline void sm_config_set_in_pin_base(pio_sm_config *c, uint in_base) {
#endif
}
-/*! \brief Set the base fpr the 'in' pins in a state machine configuration
+/*! \brief Set the base for the 'in' pins in a state machine configuration
* \ingroup sm_config
*
* 'in' pins can overlap with the 'out', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
- * \param in_base 0-31 First pin to use as input
+ * \param in_base First pin to use as input. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_in_pins(pio_sm_config *c, uint in_base) {
sm_config_set_in_pin_base(c, in_base);
}
+/*! \brief Set the count of 'in' pins in a state machine configuration
+ * \ingroup sm_config
+ *
+ * When reading pins using the IN pin mapping, this many (low) bits will be read, with the rest taking
+ * the value zero.
+ *
+ * \if rp2040_specific
+ * RP2040 does not have the ability to mask unused input pins, so the in_count must be 32
+ * \endif
+ *
+ * \param c Pointer to the configuration structure to modify
+ * \param in_count 1-32 The number of pins to include when reading via the IN pin mapping
+ */
static inline void sm_config_set_in_pin_count(pio_sm_config *c, uint in_count) {
#if PICO_PIO_VERSION == 0
// can't be changed from 32 on PIO v0
@@ -390,7 +466,7 @@ static inline void sm_config_set_in_pin_count(pio_sm_config *c, uint in_count) {
#else
valid_params_if(HARDWARE_PIO, in_count && in_count <= 32);
c->shiftctrl = (c->shiftctrl & ~PIO_SM0_SHIFTCTRL_IN_COUNT_BITS) |
- ((in_count - 1) << PIO_SM0_SHIFTCTRL_IN_COUNT_LSB);
+ ((in_count & 0x1fu) << PIO_SM0_SHIFTCTRL_IN_COUNT_LSB);
#endif
}
@@ -400,7 +476,7 @@ static inline void sm_config_set_in_pin_count(pio_sm_config *c, uint in_count) {
* 'sideset' pins can overlap with the 'in', 'out' and 'set' pins
*
* \param c Pointer to the configuration structure to modify
- * \param sideset_base 0-31 base pin for 'side set'
+ * \param sideset_base First pin to use for 'side set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_sideset_pin_base(pio_sm_config *c, uint sideset_base) {
check_pio_pin_param(sideset_base);
@@ -421,7 +497,7 @@ static inline void sm_config_set_sideset_pin_base(pio_sm_config *c, uint sideset
* 'sideset' pins can overlap with the 'in', 'out' and 'set' pins
*
* \param c Pointer to the configuration structure to modify
- * \param sideset_base 0-31 base pin for 'side set'
+ * \param sideset_base First pin to use for 'side set'. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_sideset_pins(pio_sm_config *c, uint sideset_base) {
sm_config_set_sideset_pin_base(c, sideset_base);
@@ -455,26 +531,48 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool
*
* \param c Pointer to the configuration structure to modify
* \param div_int Integer part of the divisor
- * \param div_frac Fractional part in 1/256ths
+ * \param div_frac8 Fractional part in 1/256ths
* \sa sm_config_set_clkdiv()
*/
-static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int, uint8_t div_frac) {
- invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac != 0);
+static inline void sm_config_set_clkdiv_int_frac8(pio_sm_config *c, uint32_t div_int, uint8_t div_frac8) {
+ static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_INT) == 16, "");
+ invalid_params_if(HARDWARE_PIO, div_int >> 16);
+ invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0);
+ static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, "");
c->clkdiv =
- (((uint)div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
+ (((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) |
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
}
-static inline void pio_calculate_clkdiv_from_float(float div, uint16_t *div_int, uint8_t *div_frac) {
+// backwards compatibility
+static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int, uint8_t div_frac8) {
+ sm_config_set_clkdiv_int_frac8(c, div_int, div_frac8);
+}
+
+static inline void pio_calculate_clkdiv8_from_float(float div, uint32_t *div_int, uint8_t *div_frac8) {
valid_params_if(HARDWARE_PIO, div >= 1 && div <= 65536);
+ const int frac_bit_count = REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC);
+#if PICO_PIO_CLKDIV_ROUND_NEAREST
+ div += 0.5f / (1 << frac_bit_count); // round to the nearest 1/256
+#endif
*div_int = (uint16_t)div;
+ // not a strictly necessary check, but if this changes, then this method should
+ // probably no longer be used in favor of one with a larger fraction
+ static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, "");
if (*div_int == 0) {
- *div_frac = 0;
+ *div_frac8 = 0;
} else {
- *div_frac = (uint8_t)((div - (float)*div_int) * (1u << 8u));
+ *div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << frac_bit_count));
}
}
+// backwards compatibility
+static inline void pio_calculate_clkdiv_from_float(float div, uint16_t *div_int16, uint8_t *div_frac8) {
+ uint32_t div_int;
+ pio_calculate_clkdiv8_from_float(div, &div_int, div_frac8);
+ *div_int16 = (uint16_t) div_int;
+}
+
/*! \brief Set the state machine clock divider (from a floating point value) in a state machine configuration
* \ingroup sm_config
*
@@ -491,10 +589,10 @@ static inline void pio_calculate_clkdiv_from_float(float div, uint16_t *div_int,
* although it will depend on the use case.
*/
static inline void sm_config_set_clkdiv(pio_sm_config *c, float div) {
- uint16_t div_int;
- uint8_t div_frac;
- pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
- sm_config_set_clkdiv_int_frac(c, div_int, div_frac);
+ uint32_t div_int;
+ uint8_t div_frac8;
+ pio_calculate_clkdiv8_from_float(div, &div_int, &div_frac8);
+ sm_config_set_clkdiv_int_frac8(c, div_int, div_frac8);
}
/*! \brief Set the wrap addresses in a state machine configuration
@@ -517,15 +615,15 @@ static inline void sm_config_set_wrap(pio_sm_config *c, uint wrap_target, uint w
* \ingroup sm_config
*
* \param c Pointer to the configuration structure to modify
- * \param pin The raw GPIO pin number to use as the source for a `jmp pin` instruction
+ * \param pin The raw GPIO pin number to use as the source for a `jmp pin` instruction. See \ref sm_config_pins "sm_config_ pins" for more detail on pin arguments
*/
static inline void sm_config_set_jmp_pin(pio_sm_config *c, uint pin) {
check_pio_pin_param(pin);
c->execctrl = (c->execctrl & ~PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
((pin & 31) << PIO_SM0_EXECCTRL_JMP_PIN_LSB);
#if PICO_PIO_USE_GPIO_BASE
- c->pinhi = (c->pinhi & ~(31u << 24)) |
- ((pin >> 4) << 24);
+ c->pinhi = (c->pinhi & ~(31u << 20)) |
+ ((pin >> 4) << 20);
#endif
}
@@ -596,15 +694,15 @@ static inline void sm_config_set_fifo_join(pio_sm_config *c, enum pio_fifo_join
* \param c Pointer to the configuration structure to modify
* \param sticky to enable 'sticky' output (i.e. re-asserting most recent OUT/SET pin values on subsequent cycles)
* \param has_enable_pin true to enable auxiliary OUT enable pin
- * \param enable_pin_index pin index for auxiliary OUT enable
- */
-static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin, uint enable_pin_index) {
+ * \param enable_bit_index Data bit index for auxiliary OUT enable.
+*/
+static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin, uint enable_bit_index) {
c->execctrl = (c->execctrl &
(uint)~(PIO_SM0_EXECCTRL_OUT_STICKY_BITS | PIO_SM0_EXECCTRL_INLINE_OUT_EN_BITS |
PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS)) |
(bool_to_bit(sticky) << PIO_SM0_EXECCTRL_OUT_STICKY_LSB) |
(bool_to_bit(has_enable_pin) << PIO_SM0_EXECCTRL_INLINE_OUT_EN_LSB) |
- ((enable_pin_index << PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) & PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS);
+ ((enable_bit_index << PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) & PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS);
}
/*! \brief Set source for 'mov status' in a state machine configuration
@@ -634,7 +732,7 @@ static inline void sm_config_set_mov_status(pio_sm_config *c, enum pio_mov_statu
* --------|--------
* Out Pins | 32 starting at 0
* Set Pins | 0 starting at 0
- * In Pins (base) | 0
+ * In Pins | 32 starting at 0
* Side Set Pins (base) | 0
* Side Set | disabled
* Wrap | wrap=31, wrap_to=0
@@ -647,11 +745,11 @@ static inline void sm_config_set_mov_status(pio_sm_config *c, enum pio_mov_statu
* \return the default state machine configuration which can then be modified.
*/
static inline pio_sm_config pio_get_default_sm_config(void) {
- pio_sm_config c = {0};
+ pio_sm_config c = {};
#if PICO_PIO_USE_GPIO_BASE
c.pinhi = -1;
#endif
- sm_config_set_clkdiv_int_frac(&c, 1, 0);
+ sm_config_set_clkdiv_int_frac8(&c, 1, 0);
sm_config_set_wrap(&c, 0, 31);
sm_config_set_in_shift(&c, true, false, 32);
sm_config_set_out_shift(&c, true, false, 32);
@@ -677,9 +775,21 @@ static inline uint pio_get_gpio_base(PIO pio) {
#endif
}
+static inline void check_pio_pin_mask64(__unused PIO pio, __unused uint sm, __unused uint64_t pinmask) {
+ // check no pins are set in the mask which are incompatible with the pio
+#if PICO_PIO_USE_GPIO_BASE
+ valid_params_if(HARDWARE_PIO, (pinmask & ~(0xffffffffull << pio_get_gpio_base(pio))) == 0);
+#else
+ valid_params_if(HARDWARE_PIO, (pinmask & ~0xffffffffull) == 0);
+#endif
+}
+
/*! \brief Apply a state machine configuration to a state machine
* \ingroup hardware_pio
*
+ * \if rp2350_specific
+ * See \ref sm_config_pins "sm_config_ pins" for more detail on why this method might fail on RP2350B
+ * \endif
* \param pio Handle to PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param config the configuration to apply
@@ -689,7 +799,6 @@ static inline int pio_sm_set_config(PIO pio, uint sm, const pio_sm_config *confi
check_pio_param(pio);
check_sm_param(sm);
pio->sm[sm].clkdiv = config->clkdiv;
- pio->sm[sm].execctrl = config->execctrl;
pio->sm[sm].shiftctrl = config->shiftctrl;
#if PICO_PIO_USE_GPIO_BASE
uint used = (~config->pinhi >> 4) & PINHI_ALL_PIN_LSBS;
@@ -700,11 +809,14 @@ static inline int pio_sm_set_config(PIO pio, uint sm, const pio_sm_config *confi
uint gpio_base = pio_get_gpio_base(pio);
invalid_params_if_and_return(PIO, gpio_under_16 && gpio_base, PICO_ERROR_BAD_ALIGNMENT);
invalid_params_if_and_return(PIO, gpio_over_32 && !gpio_base, PICO_ERROR_BAD_ALIGNMENT);
- // flip the top bit of any used (pinctrl) values to turn:
+ // flip the top bit of any used (execctrl/pinctrl) values to turn:
// bit6(32) + 0-15 -> base(16) + 16-31
// bit6(0) + 16-31 -> base(16) + 0-15
+ static_assert(PINHI_EXECCTRL_LSB == 20, ""); // we use shifts to mask off bits below
+ pio->sm[sm].execctrl = config->execctrl ^ (gpio_base ? ((used >> 20) << (PIO_SM0_EXECCTRL_JMP_PIN_LSB + 4)) : 0);
pio->sm[sm].pinctrl = config->pinctrl ^ (gpio_base ? ((used << 12) >> 8) : 0);
#else
+ pio->sm[sm].execctrl = config->execctrl;
pio->sm[sm].pinctrl = config->pinctrl;
#endif
return PICO_OK;
@@ -792,6 +904,9 @@ typedef struct pio_program {
* instance must specify a base GPIO where the instance's "pin 0" maps. For RP2350 the valid
* values are 0 and 16, indicating the PIO instance has access to pins 0-31, or 16-47 respectively.
*
+ * NOTE: This method simply changes the underlying PIO register, it does not detect or attempt
+ * to prevent any side effects this change will have on in use state machines on this PIO.
+ *
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param gpio_base the GPIO base (either 0 or 16)
* \return PICO_OK (0) on success, error code otherwise
@@ -803,7 +918,8 @@ int pio_set_gpio_base(PIO pio, uint gpio_base);
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param program the program definition
- * \return true if the program can be loaded; false if there is not suitable space in the instruction memory
+ * \return true if the program can be loaded;
+ * false if not, e.g. if there is not suitable space in the instruction memory
*/
bool pio_can_add_program(PIO pio, const pio_program_t *program);
@@ -813,7 +929,8 @@ bool pio_can_add_program(PIO pio, const pio_program_t *program);
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param program the program definition
* \param offset the instruction memory offset wanted for the start of the program
- * \return true if the program can be loaded at that location; false if there is not space in the instruction memory
+ * \return true if the program can be loaded at that location;
+ * false if not, e.g. if there is not space in the instruction memory
*/
bool pio_can_add_program_at_offset(PIO pio, const pio_program_t *program, uint offset);
@@ -870,6 +987,10 @@ void pio_clear_instruction_memory(PIO pio);
*
* The state machine is left disabled on return from this call.
*
+* * \if rp2350_specific
+ * See \ref sm_config_pins "sm_config_ pins" for more detail on why this method might fail on RP2350B
+ * \endif
+ *
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param initial_pc the initial program memory offset to run from
@@ -1359,7 +1480,7 @@ static inline void pio_sm_set_wrap(PIO pio, uint sm, uint wrap_target, uint wrap
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
- * \param out_base 0-31 First pin to set as output
+ * \param out_base First pin to set as output. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
* \param out_count 0-32 Number of pins to set.
*/
static inline void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out_count) {
@@ -1383,7 +1504,7 @@ static inline void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
- * \param set_base 0-31 First pin to set as
+ * \param set_base First pin to set as 'set'. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
* \param set_count 0-5 Number of pins to set.
*/
static inline void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set_count) {
@@ -1406,7 +1527,7 @@ static inline void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
- * \param in_base 0-31 First pin to use as input
+ * \param in_base First pin to use as input. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
static inline void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base) {
check_pio_param(pio);
@@ -1426,7 +1547,7 @@ static inline void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base) {
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
- * \param sideset_base 0-31 base pin for 'side set'
+ * \param sideset_base Base pin for 'side set'. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
static inline void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base) {
check_pio_param(pio);
@@ -1444,7 +1565,7 @@ static inline void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base)
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
- * \param pin The raw GPIO pin number to use as the source for a `jmp pin` instruction
+ * \param pin The pin number to use as the source for a `jmp pin` instruction. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
static inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint pin) {
@@ -1630,17 +1751,25 @@ void pio_sm_drain_tx_fifo(PIO pio, uint sm);
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
* \param div_int the integer part of the clock divider
- * \param div_frac the fractional part of the clock divider in 1/256s
+ * \param div_frac8 the fractional part of the clock divider in 1/256s
*/
-static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int, uint8_t div_frac) {
+static inline void pio_sm_set_clkdiv_int_frac8(PIO pio, uint sm, uint32_t div_int, uint8_t div_frac8) {
check_pio_param(pio);
check_sm_param(sm);
- invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac != 0);
+ static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_INT) == 16, "");
+ invalid_params_if(HARDWARE_PIO, div_int >> 16);
+ invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0);
+ static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, "");
pio->sm[sm].clkdiv =
- (((uint)div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
+ (((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) |
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
}
+// backwards compatibility
+static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int, uint8_t div_frac8) {
+ pio_sm_set_clkdiv_int_frac8(pio, sm, div_int, div_frac8);
+}
+
/*! \brief set the current clock divider for a state machine
* \ingroup hardware_pio
*
@@ -1651,10 +1780,10 @@ static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int
static inline void pio_sm_set_clkdiv(PIO pio, uint sm, float div) {
check_pio_param(pio);
check_sm_param(sm);
- uint16_t div_int;
- uint8_t div_frac;
- pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
- pio_sm_set_clkdiv_int_frac(pio, sm, div_int, div_frac);
+ uint32_t div_int;
+ uint8_t div_frac8;
+ pio_calculate_clkdiv8_from_float(div, &div_int, &div_frac8);
+ pio_sm_set_clkdiv_int_frac8(pio, sm, div_int, div_frac8);
}
/*! \brief Clear a state machine's TX and RX FIFOs
@@ -1678,13 +1807,28 @@ static inline void pio_sm_clear_fifos(PIO pio, uint sm) {
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
+ * Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pins64
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
- * \param pin_values the pin values to set
+ * \param pin_values the pin values to set. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
+/*! \brief Use a state machine to set a value on all pins for the PIO instance
+ * \ingroup hardware_pio
+ *
+ * This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set values on all 32 pins,
+ * before restoring the state machine's pin configuration to what it was.
+ *
+ * This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
+ *
+ * \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
+ * \param sm State machine index (0..3) to use
+ * \param pin_values the pin values to set. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
+ */
+void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pin_values);
+
/*! \brief Use a state machine to set a value on multiple pins for the PIO instance
* \ingroup hardware_pio
*
@@ -1692,14 +1836,30 @@ void pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values);
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
+* Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pins_with_mask64
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
* \param pin_values the pin values to set (if the corresponding bit in pin_mask is set)
- * \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied.
+ * \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
*/
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask);
+/*! \brief Use a state machine to set a value on multiple pins for the PIO instance
+ * \ingroup hardware_pio
+ *
+ * This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set values on up to 32 pins,
+ * before restoring the state machine's pin configuration to what it was.
+ *
+ * This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled.
+ *
+ * \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
+ * \param sm State machine index (0..3) to use
+ * \param pin_values the pin values to set (if the corresponding bit in pin_mask is set)
+ * \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
+ */
+void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask);
+
/*! \brief Use a state machine to set the pin directions for multiple pins for the PIO instance
* \ingroup hardware_pio
*
@@ -1707,6 +1867,7 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t p
* before restoring the state machine's pin configuration to what it was.
*
* This method is provided as a convenience to set initial pin directions, and should not be used against a state machine that is enabled.
+ * Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pindirs_with_mask64
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
@@ -1715,6 +1876,21 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t p
*/
void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pin_dirs, uint32_t pin_mask);
+/*! \brief Use a state machine to set the pin directions for multiple pins for the PIO instance
+ * \ingroup hardware_pio
+ *
+ * This method repeatedly reconfigures the target state machine's pin configuration and executes 'set' instructions to set pin directions on up to 32 pins,
+ * before restoring the state machine's pin configuration to what it was.
+ *
+ * This method is provided as a convenience to set initial pin directions, and should not be used against a state machine that is enabled.
+ *
+ * \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
+ * \param sm State machine index (0..3) to use
+ * \param pin_dirs the pin directions to set - 1 = out, 0 = in (if the corresponding bit in pin_mask is set)
+ * \param pin_mask a bit for each pin to indicate whether the corresponding pin_value for that pin should be applied.
+ */
+void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pin_dirs, uint64_t pin_mask);
+
/*! \brief Use a state machine to set the same pin direction for multiple consecutive pins for the PIO instance
* \ingroup hardware_pio
*
@@ -1725,7 +1901,7 @@ void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pin_dirs, uint32_t
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param sm State machine index (0..3) to use
- * \param pins_base the first pin to set a direction for
+ * \param pins_base the first pin to set a direction for. See \ref pio_sm_pins "pio_sm_ pins" for more detail on pin arguments
* \param pin_count the count of consecutive pins to set the direction for
* \param is_out the direction to set; true = out, false = in
* \return PICO_OK (0) on success, error code otherwise
@@ -1806,14 +1982,14 @@ bool pio_claim_free_sm_and_add_program(const pio_program_t *program, PIO *pio, u
* must be set per PIO instance to either address the 32 GPIOs (0->31) or the 32 GPIOS (16-47). No single
* PIO instance can interact with both pins 0->15 or 32->47 at the same time.
*
- * This method takes additional information about the GPIO pins needed (via gpi_base and gpio_count),
+ * This method takes additional information about the GPIO pins needed (via gpio_base and gpio_count),
* and optionally will set the GPIO base (\see pio_set_gpio_base) of an unused PIO instance if necessary
*
* \param program PIO program to add
* \param pio Returns the PIO hardware instance or NULL if no PIO is available
* \param sm Returns the index of the PIO state machine that was claimed
* \param offset Returns the instruction memory offset of the start of the program
- * \param gpio_base the lowest GPIO number required
+ * \param gpio_base the lowest GPIO number required (0-47 on RP2350B, 0-31 otherwise)
* \param gpio_count the count of GPIOs required
* \param set_gpio_base if there is no free SM on a PIO instance with the right GPIO base, and there IS an unused PIO
* instance, then that PIO will be reconfigured so that this method can succeed
diff --git a/src/rp2_common/hardware_pio/pio.c b/src/rp2_common/hardware_pio/pio.c
index 120dbf3f1..ed34cd815 100644
--- a/src/rp2_common/hardware_pio/pio.c
+++ b/src/rp2_common/hardware_pio/pio.c
@@ -205,11 +205,20 @@ void pio_clear_instruction_memory(PIO pio) {
hw_claim_unlock(save);
}
+#if !PICO_PIO_USE_GPIO_BASE
+// the 32 pin APIs are the same as the internal method, so collapse them
+#define pio_sm_set_pins_internal pio_sm_set_pins
+#define pio_sm_set_pins_with_mask_internal pio_sm_set_pins_with_mask
+#define pio_sm_set_pindirs_with_mask_internal pio_sm_set_pindirs_with_mask
+#endif
+
// Set the value of all PIO pins. This is done by forcibly executing
// instructions on a "victim" state machine, sm. Ideally you should choose one
// which is not currently running a program. This is intended for one-time
// setup of initial pin states.
-void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
+//
+// note pin mask bit 0 is relative to current GPIO_BASE
+void pio_sm_set_pins_internal(PIO pio, uint sm, uint32_t pins) {
check_pio_param(pio);
check_sm_param(sm);
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
@@ -231,7 +240,25 @@ void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
pio->sm[sm].execctrl = execctrl_saved;
}
-void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pinvals, uint32_t pin_mask) {
+#ifndef pio_sm_set_pins_internal
+void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
+#if PICO_PIO_USE_GPIO_BASE
+ pins >>= pio_get_gpio_base(pio);
+#endif
+ pio_sm_set_pins_internal(pio, sm, pins);
+}
+#endif
+
+void pio_sm_set_pins64(PIO pio, uint sm, uint64_t pins) {
+ check_pio_pin_mask64(pio, sm, pins);
+#if PICO_PIO_USE_GPIO_BASE
+ pins >>= pio_get_gpio_base(pio);
+#endif
+ pio_sm_set_pins_internal(pio, sm, (uint32_t)pins);
+}
+
+// note pin values/mask bit 0 is relative to current GPIO_BASE
+void pio_sm_set_pins_with_mask_internal(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
check_pio_param(pio);
check_sm_param(sm);
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
@@ -242,14 +269,33 @@ void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pinvals, uint32_t pin_
pio->sm[sm].pinctrl =
(1u << PIO_SM0_PINCTRL_SET_COUNT_LSB) |
(base << PIO_SM0_PINCTRL_SET_BASE_LSB);
- pio_sm_exec(pio, sm, pio_encode_set(pio_pins, (pinvals >> base) & 0x1u));
+ pio_sm_exec(pio, sm, pio_encode_set(pio_pins, (pin_values >> base) & 0x1u));
pin_mask &= pin_mask - 1;
}
pio->sm[sm].pinctrl = pinctrl_saved;
pio->sm[sm].execctrl = execctrl_saved;
}
-void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
+#ifndef pio_sm_set_pins_with_mask_internal
+void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
+#if PICO_PIO_USE_GPIO_BASE
+ pin_values >>= pio_get_gpio_base(pio);
+ pin_mask >>= pio_get_gpio_base(pio);
+#endif
+ pio_sm_set_pins_with_mask_internal(pio, sm, pin_values, pin_mask);
+}
+#endif
+
+void pio_sm_set_pins_with_mask64(PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask) {
+ check_pio_pin_mask64(pio, sm, pin_mask);
+#if PICO_PIO_USE_GPIO_BASE
+ pin_values >>= pio_get_gpio_base(pio);
+ pin_mask >>= pio_get_gpio_base(pio);
+#endif
+ pio_sm_set_pins_with_mask_internal(pio, sm, (uint32_t)pin_values, (uint32_t)pin_mask);
+}
+
+void pio_sm_set_pindirs_with_mask_internal(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
check_pio_param(pio);
check_sm_param(sm);
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
@@ -267,6 +313,24 @@ void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t p
pio->sm[sm].execctrl = execctrl_saved;
}
+#ifndef pio_sm_set_pindirs_with_mask_internal
+void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
+#if PICO_PIO_USE_GPIO_BASE
+ pindirs >>= pio_get_gpio_base(pio);
+ pin_mask >>= pio_get_gpio_base(pio);
+#endif
+ pio_sm_set_pindirs_with_mask_internal(pio, sm, pindirs, pin_mask);
+}
+#endif
+
+void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t pin_mask) {
+#if PICO_PIO_USE_GPIO_BASE
+ pindirs >>= pio_get_gpio_base(pio);
+ pin_mask >>= pio_get_gpio_base(pio);
+#endif
+ pio_sm_set_pindirs_with_mask_internal(pio, sm, (uint32_t)pindirs, (uint32_t)pin_mask);
+}
+
int pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin, uint count, bool is_out) {
check_pio_param(pio);
check_sm_param(sm);
diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h
index d394c7215..19258ab57 100644
--- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h
+++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h
@@ -103,6 +103,11 @@ static_assert(DREQ_PWM_WRAP7 == DREQ_PWM_WRAP0 + 7, "");
})
#endif
+// PICO_CONFIG: PICO_PWM_CLKDIV_ROUND_NEAREST, True if floating point PWM clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_pwm
+#ifndef PICO_PWM_CLKDIV_ROUND_NEAREST
+#define PICO_PWM_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
+#endif
+
static inline void check_slice_num_param(__unused uint slice_num) {
valid_params_if(HARDWARE_PWM, slice_num < NUM_PWM_SLICES);
}
@@ -155,39 +160,49 @@ static inline void pwm_config_set_phase_correct(pwm_config *c, bool phase_correc
*/
static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
valid_params_if(HARDWARE_PWM, div >= 1.f && div < 256.f);
- c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB));
+ const int frac_bit_count = REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC);
+#if PICO_PWM_CLKDIV_ROUND_NEAREST
+ div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
+#endif
+ c->div = (uint32_t)(div * (float)(1u << frac_bit_count));
}
/** \brief Set PWM clock divider in a PWM configuration using an 8:4 fractional value
* \ingroup hardware_pwm
*
* \param c PWM configuration struct to modify
- * \param integer 8 bit integer part of the clock divider. Must be greater than or equal to 1.
- * \param fract 4 bit fractional part of the clock divider
+ * \param div_int 8 bit integer part of the clock divider. Must be greater than or equal to 1.
+ * \param div_frac4 4 bit fractional part of the clock divider
*
* If the divide mode is free-running, the PWM counter runs at clk_sys / div.
* Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
* before passing them on to the PWM counter.
*/
-static inline void pwm_config_set_clkdiv_int_frac(pwm_config *c, uint8_t integer, uint8_t fract) {
- valid_params_if(HARDWARE_PWM, integer >= 1);
- valid_params_if(HARDWARE_PWM, fract < 16);
- c->div = (((uint)integer) << PWM_CH0_DIV_INT_LSB) | (((uint)fract) << PWM_CH0_DIV_FRAC_LSB);
+static inline void pwm_config_set_clkdiv_int_frac4(pwm_config *c, uint32_t div_int, uint8_t div_frac4) {
+ static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_INT) == 8, "");
+ valid_params_if(HARDWARE_PWM, div_int >= 1 && div_int < 256);
+ static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, "");
+ valid_params_if(HARDWARE_PWM, div_frac4 < 16);
+ c->div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
+}
+
+// backwards compatibility
+static inline void pwm_config_set_clkdiv_int_frac(pwm_config *c, uint8_t div_int, uint8_t div_frac4) {
+ pwm_config_set_clkdiv_int_frac4(c, div_int, div_frac4);
}
/** \brief Set PWM clock divider in a PWM configuration
* \ingroup hardware_pwm
*
* \param c PWM configuration struct to modify
- * \param div Integer value to reduce counting rate by. Must be greater than or equal to 1.
+ * \param div_int Integer value to reduce counting rate by. Must be greater than or equal to 1 and less than 256.
*
* If the divide mode is free-running, the PWM counter runs at clk_sys / div.
* Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
* before passing them on to the PWM counter.
*/
-static inline void pwm_config_set_clkdiv_int(pwm_config *c, uint div) {
- valid_params_if(HARDWARE_PWM, div >= 1 && div < 256);
- pwm_config_set_clkdiv_int_frac(c, (uint8_t)div, 0);
+static inline void pwm_config_set_clkdiv_int(pwm_config *c, uint32_t div_int) {
+ pwm_config_set_clkdiv_int_frac4(c, div_int, 0);
}
/** \brief Set PWM counting mode in a PWM configuration
@@ -427,14 +442,20 @@ static inline void pwm_retard_count(uint slice_num) {
* Set the clock divider. Counter increment will be on sysclock divided by this value, taking into account the gating.
*
* \param slice_num PWM slice number
- * \param integer 8 bit integer part of the clock divider
- * \param fract 4 bit fractional part of the clock divider
+ * \param div_int 8 bit integer part of the clock divider
+ * \param div_frac4 4 bit fractional part of the clock divider
*/
-static inline void pwm_set_clkdiv_int_frac(uint slice_num, uint8_t integer, uint8_t fract) {
+static inline void pwm_set_clkdiv_int_frac4(uint slice_num, uint8_t div_int, uint8_t div_frac4) {
check_slice_num_param(slice_num);
- valid_params_if(HARDWARE_PWM, integer >= 1);
- valid_params_if(HARDWARE_PWM, fract < 16);
- pwm_hw->slice[slice_num].div = (((uint)integer) << PWM_CH0_DIV_INT_LSB) | (((uint)fract) << PWM_CH0_DIV_FRAC_LSB);
+ valid_params_if(HARDWARE_PWM, div_int >= 1);
+ static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, "");
+ valid_params_if(HARDWARE_PWM, div_frac4 < 16);
+ pwm_hw->slice[slice_num].div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
+}
+
+// backwards compatibility
+static inline void pwm_set_clkdiv_int_frac(uint slice_num, uint8_t div_int, uint8_t div_frac4) {
+ pwm_set_clkdiv_int_frac4(slice_num, div_int, div_frac4);
}
/** \brief Set PWM clock divider
@@ -450,7 +471,7 @@ static inline void pwm_set_clkdiv(uint slice_num, float divider) {
valid_params_if(HARDWARE_PWM, divider >= 1.f && divider < 256.f);
uint8_t i = (uint8_t)divider;
uint8_t f = (uint8_t)((divider - i) * (0x01 << 4));
- pwm_set_clkdiv_int_frac(slice_num, i, f);
+ pwm_set_clkdiv_int_frac4(slice_num, i, f);
}
/** \brief Set PWM output polarity
@@ -655,7 +676,7 @@ static inline void pwm_set_irq_mask_enabled(uint32_t slice_mask, bool enabled) {
hw_clear_bits(&pwm_hw->inte, slice_mask);
}
#else
- static_assert(PWM_IRQ_WRAP_1 == PWM_IRQ_WRAP_0 + 1);
+ static_assert(PWM_IRQ_WRAP_1 == PWM_IRQ_WRAP_0 + 1, "");
uint irq_index = PWM_DEFAULT_IRQ_NUM() - PWM_IRQ_WRAP_0;
if (enabled) {
hw_set_bits(&pwm_hw->irq_ctrl[irq_index].inte, slice_mask);
@@ -761,7 +782,7 @@ static inline uint32_t pwm_get_irq1_status_mask(void) {
* \return Bitmask of all PWM interrupts currently set
*/
static inline uint32_t pwm_irqn_get_status_mask(uint irq_index) {
- invalid_params_if(HARDWARE_PWM, irq_index >= NUM_DMA_IRQS);
+ invalid_params_if(HARDWARE_PWM, irq_index >= NUM_PWM_IRQS);
return pwm_hw->irq_ctrl[irq_index].ints;
}
diff --git a/src/rp2_common/hardware_spi/include/hardware/spi.h b/src/rp2_common/hardware_spi/include/hardware/spi.h
index 2f3b84e6b..cf79645da 100644
--- a/src/rp2_common/hardware_spi/include/hardware/spi.h
+++ b/src/rp2_common/hardware_spi/include/hardware/spi.h
@@ -40,10 +40,10 @@ extern "C" {
*/
// PICO_CONFIG: PICO_DEFAULT_SPI, Define the default SPI for a board, min=0, max=1, default=Usually provided via board header, group=hardware_spi
-// PICO_CONFIG: PICO_DEFAULT_SPI_SCK_PIN, Define the default SPI SCK pin, min=0, max=29, default=Usually provided via board header, group=hardware_spi
-// PICO_CONFIG: PICO_DEFAULT_SPI_TX_PIN, Define the default SPI TX pin, min=0, max=29, default=Usually provided via board header, group=hardware_spi
-// PICO_CONFIG: PICO_DEFAULT_SPI_RX_PIN, Define the default SPI RX pin, min=0, max=29, default=Usually provided via board header, group=hardware_spi
-// PICO_CONFIG: PICO_DEFAULT_SPI_CSN_PIN, Define the default SPI CSN pin, min=0, max=29, default=Usually provided via board header, group=hardware_spi
+// PICO_CONFIG: PICO_DEFAULT_SPI_SCK_PIN, Define the default SPI SCK pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
+// PICO_CONFIG: PICO_DEFAULT_SPI_TX_PIN, Define the default SPI TX pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
+// PICO_CONFIG: PICO_DEFAULT_SPI_RX_PIN, Define the default SPI RX pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
+// PICO_CONFIG: PICO_DEFAULT_SPI_CSN_PIN, Define the default SPI CSN pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
/**
* \brief Opaque type representing an SPI instance.
diff --git a/src/rp2_common/hardware_timer/include/hardware/timer.h b/src/rp2_common/hardware_timer/include/hardware/timer.h
index 7f14aa25e..2e8434e12 100644
--- a/src/rp2_common/hardware_timer/include/hardware/timer.h
+++ b/src/rp2_common/hardware_timer/include/hardware/timer.h
@@ -105,7 +105,7 @@ extern "C" {
#ifndef TIMER_ALARM_IRQ_NUM
#if NUM_GENERIC_TIMERS == 1
static_assert(TIMER_IRQ_3 == TIMER_IRQ_0 + 3, "");
-#define TIMER_ALARM_IRQ_NUM(timer, alarm_num) (TIMER_IRQ_0 + (alarm_num))
+#define TIMER_ALARM_IRQ_NUM(timer, alarm_num) ({ ((void)(timer)); (TIMER_IRQ_0 + (alarm_num)); })
#else
static_assert(TIMER1_IRQ_3 == TIMER0_IRQ_0 + 7, "");
#define TIMER_ALARM_IRQ_NUM(timer, alarm_num) (TIMER0_IRQ_0 + TIMER_NUM(timer) * NUM_ALARMS + (alarm_num))
@@ -116,7 +116,7 @@ static_assert(TIMER1_IRQ_3 == TIMER0_IRQ_0 + 7, "");
* \def TIMER_ALARM_NUM_FROM_IRQ(irq_num)
* \ingroup hardware_timer
* \hideinitializer
- * \brief Returns the alarm number from an \irq_num_t. See \ref TIMER_INSTANCE_NUM_FROM_IRQ to get the timer instance number
+ * \brief Returns the alarm number from an \ref irq_num_t. See \ref TIMER_INSTANCE_NUM_FROM_IRQ to get the timer instance number
*
* Note this macro is intended to resolve at compile time, and does no parameter checking
*/
@@ -134,7 +134,7 @@ static_assert(TIMER1_IRQ_3 == TIMER0_IRQ_0 + 7, "");
* \def TIMER_NUM_FROM_IRQ(irq_num)
* \ingroup hardware_timer
* \hideinitializer
- * \brief Returns the alarm number from an \irq_num_t. See \ref TIMER_INSTANCE_NUM_FROM_IRQ to get the alarm number
+ * \brief Returns the alarm number from an \ref irq_num_t. See \ref TIMER_INSTANCE_NUM_FROM_IRQ to get the alarm number
*
* Note this macro is intended to resolve at compile time, and does no parameter checking
*/
@@ -557,7 +557,7 @@ void hardware_alarm_force_irq(uint alarm_num);
* \param alarm_num the alarm number
* \sa TIMER_ALARM_IRQ_NUM
*/
-static inline uint timer_hardware_alarm_get_irq_num(__unused timer_hw_t *timer, uint alarm_num) {
+static inline uint timer_hardware_alarm_get_irq_num(timer_hw_t *timer, uint alarm_num) {
check_hardware_alarm_num_param(alarm_num);
return TIMER_ALARM_IRQ_NUM(timer, alarm_num);
}
@@ -565,10 +565,9 @@ static inline uint timer_hardware_alarm_get_irq_num(__unused timer_hw_t *timer,
/**
* \ingroup hardware_timer
* \brief Returns the \ref irq_num_t for the alarm interrupt from the given alarm on the default timer instance
- * \param timer the timer instance
* \param alarm_num the alarm number
*/
-static inline uint hardware_alarm_get_irq_num(timer_hw_t *timer, uint alarm_num) {
+static inline uint hardware_alarm_get_irq_num(uint alarm_num) {
return timer_hardware_alarm_get_irq_num(PICO_DEFAULT_TIMER_INSTANCE(), alarm_num);
}
diff --git a/src/rp2_common/hardware_timer/timer.c b/src/rp2_common/hardware_timer/timer.c
index 890b047bd..c9fc61606 100644
--- a/src/rp2_common/hardware_timer/timer.c
+++ b/src/rp2_common/hardware_timer/timer.c
@@ -150,9 +150,10 @@ void busy_wait_until(absolute_time_t t) {
*/
void hardware_alarm_irq_handler(void* data) {
// Determine which timer this IRQ is for
- uint alarm_num = TIMER_ALARM_NUM_FROM_IRQ(__get_current_exception() - VTABLE_FIRST_IRQ);
+ uint irq_num = __get_current_exception() - VTABLE_FIRST_IRQ;
+ uint alarm_num = TIMER_ALARM_NUM_FROM_IRQ(irq_num);
check_hardware_alarm_num_param(alarm_num);
- uint timer_num = TIMER_NUM_FROM_IRQ(alarm_num);
+ uint timer_num = TIMER_NUM_FROM_IRQ(irq_num);
timer_hw_t *timer = timer_get_instance(timer_num);
hardware_alarm_callback_t callback = NULL;
diff --git a/src/rp2_common/hardware_uart/BUILD.bazel b/src/rp2_common/hardware_uart/BUILD.bazel
index f8694bff3..fe5a34574 100644
--- a/src/rp2_common/hardware_uart/BUILD.bazel
+++ b/src/rp2_common/hardware_uart/BUILD.bazel
@@ -1,7 +1,14 @@
load("//bazel:defs.bzl", "compatible_with_rp2")
+load("//bazel/util:sdk_define.bzl", "pico_sdk_define")
package(default_visibility = ["//visibility:public"])
+pico_sdk_define(
+ name = "PICO_DEFAULT_UART_BAUD_RATE",
+ define_name = "PICO_DEFAULT_UART_BAUD_RATE",
+ from_flag = "//bazel/config:PICO_DEFAULT_UART_BAUD_RATE",
+)
+
cc_library(
name = "hardware_uart",
srcs = ["uart.c"],
@@ -9,6 +16,7 @@ cc_library(
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
+ ":PICO_DEFAULT_UART_BAUD_RATE",
"//src/rp2_common:hardware_regs",
"//src/rp2_common:hardware_structs",
"//src/rp2_common:pico_platform",
diff --git a/src/rp2_common/hardware_uart/CMakeLists.txt b/src/rp2_common/hardware_uart/CMakeLists.txt
index 85edd9420..8461d25bf 100644
--- a/src/rp2_common/hardware_uart/CMakeLists.txt
+++ b/src/rp2_common/hardware_uart/CMakeLists.txt
@@ -2,7 +2,7 @@ pico_simple_hardware_target(uart)
pico_mirrored_target_link_libraries(hardware_uart INTERFACE hardware_resets hardware_clocks)
-# PICO_CONFIG: PICO_DEFAULT_UART_BAUD_RATE, Define the default UART baudrate, max=921600, default=115200, group=hardware_uart
+# PICO_CMAKE_CONFIG: PICO_DEFAULT_UART_BAUD_RATE, Define the default UART baudrate, type=int, max=921600, default=115200, group=hardware_uart
if (PICO_DEFAULT_UART_BAUD_RATE)
target_compile_definitions(hardware_uart INTERFACE
PICO_DEFAULT_UART_BAUD_RATE=${PICO_DEFAULT_UART_BAUD_RATE})
diff --git a/src/rp2_common/hardware_uart/include/hardware/uart.h b/src/rp2_common/hardware_uart/include/hardware/uart.h
index 4febe1799..917749e99 100644
--- a/src/rp2_common/hardware_uart/include/hardware/uart.h
+++ b/src/rp2_common/hardware_uart/include/hardware/uart.h
@@ -34,8 +34,8 @@ extern "C" {
#endif
// PICO_CONFIG: PICO_DEFAULT_UART, Define the default UART used for printf etc, min=0, max=1, default=Usually provided via board header, group=hardware_uart
-// PICO_CONFIG: PICO_DEFAULT_UART_TX_PIN, Define the default UART TX pin, min=0, max=29, default=Usually provided via board header, group=hardware_uart
-// PICO_CONFIG: PICO_DEFAULT_UART_RX_PIN, Define the default UART RX pin, min=0, max=29, default=Usually provided via board header, group=hardware_uart
+// PICO_CONFIG: PICO_DEFAULT_UART_TX_PIN, Define the default UART TX pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_uart
+// PICO_CONFIG: PICO_DEFAULT_UART_RX_PIN, Define the default UART RX pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_uart
// PICO_CONFIG: PICO_DEFAULT_UART_BAUD_RATE, Define the default UART baudrate, max=921600, default=115200, group=hardware_uart
#ifndef PICO_DEFAULT_UART_BAUD_RATE
@@ -213,7 +213,7 @@ static_assert(UART1_IRQ == UART0_IRQ + 1, "");
* \ingroup hardware_uart
*
* \param uart UART instance
- * \return Number of UART, 0 or 1.
+ * \return Number of UART, 0 or 1
*/
static inline uint uart_get_index(uart_inst_t *uart) {
invalid_params_if(HARDWARE_UART, uart != uart0 && uart != uart1);
@@ -223,8 +223,8 @@ static inline uint uart_get_index(uart_inst_t *uart) {
/*! \brief Get the UART instance from an instance number
* \ingroup hardware_uart
*
- * \param uart UART instance
- * \return Number of UART, 0 or 1
+ * \param num Number of UART, 0 or 1
+ * \return UART instance
*/
static inline uart_inst_t *uart_get_instance(uint num) {
invalid_params_if(HARDWARE_UART, num >= NUM_UARTS);
@@ -598,11 +598,10 @@ static inline uint uart_get_dreq_num(uart_inst_t *uart, bool is_tx) {
return UART_DREQ_NUM(uart, is_tx);
}
-/*! \brief Return the \ref reset_num_t to use for pacing transfers to/from a particular UART instance
+/*! \brief Return the \ref reset_num_t to use to reset a particular UART instance
* \ingroup hardware_uart
*
* \param uart UART instance. \ref uart0 or \ref uart1
- * \param is_tx true for sending data to the UART instance, false for receiving data from the UART instance
*/
static inline uint uart_get_reset_num(uart_inst_t *uart) {
return UART_RESET_NUM(uart);
diff --git a/src/rp2_common/hardware_watchdog/CMakeLists.txt b/src/rp2_common/hardware_watchdog/CMakeLists.txt
index 2577c75ba..6d19afe46 100644
--- a/src/rp2_common/hardware_watchdog/CMakeLists.txt
+++ b/src/rp2_common/hardware_watchdog/CMakeLists.txt
@@ -1,3 +1,3 @@
pico_simple_hardware_target(watchdog)
-pico_mirrored_target_link_libraries(hardware_watchdog INTERFACE hardware_ticks)
\ No newline at end of file
+pico_mirrored_target_link_libraries(hardware_watchdog INTERFACE hardware_ticks pico_bootrom)
diff --git a/src/rp2_common/hardware_xip_cache/BUILD.bazel b/src/rp2_common/hardware_xip_cache/BUILD.bazel
new file mode 100644
index 000000000..df81b8e31
--- /dev/null
+++ b/src/rp2_common/hardware_xip_cache/BUILD.bazel
@@ -0,0 +1,14 @@
+load("//bazel:defs.bzl", "compatible_with_rp2")
+
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "hardware_xip_cache",
+ srcs = ["xip_cache.c"],
+ hdrs = ["include/hardware/xip_cache.h"],
+ includes = ["include"],
+ target_compatible_with = compatible_with_rp2(),
+ deps = [
+ "//src/rp2_common/hardware_sync",
+ ],
+)
diff --git a/src/rp2_common/hardware_xip_cache/CMakeLists.txt b/src/rp2_common/hardware_xip_cache/CMakeLists.txt
new file mode 100644
index 000000000..7a94b0c05
--- /dev/null
+++ b/src/rp2_common/hardware_xip_cache/CMakeLists.txt
@@ -0,0 +1,3 @@
+pico_simple_hardware_target(xip_cache)
+
+pico_mirrored_target_link_libraries(hardware_xip_cache INTERFACE hardware_sync)
diff --git a/src/rp2_common/hardware_xip_cache/include/hardware/xip_cache.h b/src/rp2_common/hardware_xip_cache/include/hardware/xip_cache.h
new file mode 100644
index 000000000..286db8bdc
--- /dev/null
+++ b/src/rp2_common/hardware_xip_cache/include/hardware/xip_cache.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_XIP_CACHE_H
+#define _HARDWARE_XIP_CACHE_H
+
+#include "pico.h"
+#include "hardware/regs/addressmap.h"
+
+/** \file xip_cache.h
+ * \defgroup hardware_xip_cache hardware_xip_cache
+ *
+ * \brief Low-level cache maintenance operations for the XIP cache
+ *
+ * These functions apply some maintenance operation to either the entire cache contents, or a range
+ * of offsets within the downstream address space. Offsets start from 0 (indicating the first byte
+ * of flash), so pointers should have XIP_BASE subtracted before passing into one of these
+ * functions.
+ *
+ * \if rp2040-specific
+ * The only valid cache maintenance operation on RP2040 is "invalidate", which tells the cache to
+ * forget everything it knows about some address. This is necessary after a programming operation,
+ * because the cache does not automatically know about any serial programming operations performed
+ * on the external flash device, and could return stale data.
+ * \endif
+ *
+ * \if rp2350-specific
+ * On RP2350, the three types of operation are:
+ *
+ * * Invalidate: tell the cache to forget everything it knows about some address. The next access to
+ * that address will fetch from downstream memory.
+ *
+ * * Clean: if the addressed cache line contains data not yet written to external memory, then write
+ * that data out now, and mark the line as "clean" (i.e. not containing uncommitted write data)
+ *
+ * * Pin: mark an address as always being resident in the cache. This persists until the line is
+ * invalidated, and can be used to allocate part of the cache for cache-as-SRAM use.
+ *
+ * When using both external flash and external RAM (e.g. PSRAM), a simple way to maintain coherence
+ * over flash programming operations is to:
+ *
+ * 1. Clean the entire cache (e.g. using xip_cache_clean_all())
+ *
+ * 2. Erase + program the flash using serial SPI commands
+ *
+ * 3. Invalidate ("flush") the entire cache (e.g. using xip_cache_invalidate_all())
+ *
+ * The invalidate ensures the programming is visible to subsequent reads. The clean ensures that the
+ * invalidate does not discard any cached PSRAM write data.
+ *
+ * \endif
+ *
+ */
+
+// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_XIP_CACHE, Enable/disable assertions in the hardware_xip_cache module, type=bool, default=0, group=hardware_xip_cache
+#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_XIP_CACHE
+#define PARAM_ASSERTIONS_ENABLED_HARDWARE_XIP_CACHE 0
+#endif
+
+#define XIP_CACHE_LINE_SIZE _u(8)
+
+#define XIP_CACHE_SIZE (_u(16) * _u(1024))
+
+#if PICO_RP2040
+#define XIP_CACHE_ADDRESS_SPACE_SIZE (_u(16) * _u(1024) * _u(1024))
+#else
+#define XIP_CACHE_ADDRESS_SPACE_SIZE (XIP_END - XIP_BASE)
+#endif
+
+// A read-only cache never requires cleaning (you can still call the functions, they are just no-ops)
+#if PICO_RP2040
+#define XIP_CACHE_IS_READ_ONLY 1
+#else
+#define XIP_CACHE_IS_READ_ONLY 0
+#endif
+
+#ifndef __ASSEMBLER__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \brief Invalidate the cache for the entire XIP address space
+ * \ingroup hardware_xip_cache
+ *
+ * Invalidation ensures that subsequent reads will fetch data from the downstream memory, rather
+ * than using (potentially stale) cached data.
+ *
+ * This function is faster than calling xip_cache_invalidate_range() for the entire address space,
+ * because it iterates over cachelines instead of addresses.
+ *
+ * @note Any pending write data held in the cache is lost: you can force the cache to commit these
+ * writes first, by calling xip_cache_clean_all()
+ *
+ * @note Unlike flash_flush_cache(), this function affects *only* the cache line state.
+ * flash_flush_cache() calls a ROM API which can have other effects on some platforms, like
+ * cleaning up the bootrom's QSPI GPIO setup on RP2040. Prefer this function for general cache
+ * maintenance use, and prefer flash_flush_cache in sequences of ROM flash API calls.
+ */
+void xip_cache_invalidate_all(void);
+
+/*! \brief Invalidate a range of offsets within the XIP address space
+ * \ingroup hardware_xip_cache
+ *
+ * \param start_offset The first offset to be invalidated. Offset 0 means the first byte of XIP
+ * memory (e.g. flash). Pointers must have XIP_BASE subtracted before passing into this function.
+ * Must be 4-byte-aligned on RP2040. Must be a aligned to the start of a cache line
+ * (XIP_CACHE_LINE_SIZE) on other platforms.
+ *
+ * \param size_bytes The number of bytes to invalidate. Must be a multiple of 4 bytes on RP2040.
+ * Must be a multiple of XIP_CACHE_LINE_SIZE on other platforms.
+ *
+ * Invalidation ensures that subsequent reads will fetch data from the downstream memory, rather
+ * than using (potentially stale) cached data.
+
+ * @note Any pending write data held in the cache is lost: you can force the cache to commit these
+ * writes first, by calling xip_cache_clean_range() with the same parameters. Generally this is
+ * not necessary because invalidation is used with flash (write-behind via programming), and
+ * cleaning is used with PSRAM (writing through the cache).
+ *
+ */
+void xip_cache_invalidate_range(uintptr_t start_offset, uintptr_t size_bytes);
+
+#if !XIP_CACHE_IS_READ_ONLY
+
+/*! \brief Clean the cache for the entire XIP address space
+ * \ingroup hardware_xip_cache
+ *
+ * This causes the cache to write out all pending write data to the downstream memory. For example,
+ * when suspending the system with state retained in external PSRAM, this ensures all data has made
+ * it out to external PSRAM before powering down.
+ *
+ * This function is faster than calling xip_cache_clean_range() for the entire address space,
+ * because it iterates over cachelines instead of addresses.
+ *
+ * \if rp2040-specific
+ * On RP2040 this is a no-op, as the XIP cache is read-only. This is indicated by the
+ * XIP_CACHE_IS_READ_ONLY macro.
+ * \endif
+ *
+ * \if rp2350-specific
+ * On RP2350, due to the workaround applied for RP2350-E11, this function also effectively
+ * invalidates all cache lines after cleaning them. The next access to each line will miss. Avoid
+ * this by calling xip_cache_clean_range() which does not suffer this issue.
+ * \endif
+ *
+ */
+void xip_cache_clean_all(void);
+
+/*! \brief Clean a range of offsets within the XIP address space
+ * \ingroup hardware_xip_cache
+ *
+ * This causes the cache to write out pending write data at these offsets to the downstream memory.
+ *
+ * \if rp2040-specific
+ * On RP2040 this is a no-op, as the XIP cache is read-only. This is indicated by the
+ * XIP_CACHE_IS_READ_ONLY macro.
+ * \endif
+ *
+ * \param start_offset The first offset to be invalidated. Offset 0 means the first byte of XIP
+ * memory (e.g. flash). Pointers must have XIP_BASE subtracted before passing into this function.
+ * Must be aligned to the start of a cache line (XIP_CACHE_LINE_SIZE).
+ *
+ * \param size_bytes The number of bytes to clean. Must be a multiple of XIP_CACHE_LINE_SIZE.
+ */
+void xip_cache_clean_range(uintptr_t start_offset, uintptr_t size_bytes);
+
+#else
+// Stub these out inline to avoid generating a call to an empty function when they are no-ops
+static inline void xip_cache_clean_all(void) {}
+static inline void xip_cache_clean_range(uintptr_t start_offset, uintptr_t size_bytes) {
+ (void)start_offset;
+ (void)size_bytes;
+}
+#endif
+
+#if !PICO_RP2040
+
+/*! \brief Pin a range of offsets within the XIP address space
+ * \ingroup hardware_xip_cache
+ *
+ * Pinning a line at an address allocates the line exclusively for use at that address. This means
+ * that all subsequent accesses to that address will hit the cache, and will not go to downstream
+ * memory. This persists until one of two things happens:
+ *
+ * * The line is invalidated, e.g. via xip_cache_invalidate_all()
+ *
+ * * The same line is pinned at a different address (note lines are selected by address modulo
+ * XIP_CACHE_SIZE)
+ *
+ * \param start_offset The first offset to be pinnned. Offset 0 means the first byte of XIP
+ * memory (e.g. flash). Pointers must have XIP_BASE subtracted before passing into this function.
+ * Must be aligned to the start of a cache line (XIP_CACHE_LINE_SIZE).
+ *
+ * \param size_bytes The number of bytes to pin. Must be a multiple of XIP_CACHE_LINE_SIZE.
+ *
+ */
+void xip_cache_pin_range(uintptr_t start_offset, uintptr_t size_bytes);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !__ASSEMBLER__
+
+#endif // !_HARDWARE_XIP_CACHE_H
diff --git a/src/rp2_common/hardware_xip_cache/xip_cache.c b/src/rp2_common/hardware_xip_cache/xip_cache.c
new file mode 100644
index 000000000..5a78ec0f4
--- /dev/null
+++ b/src/rp2_common/hardware_xip_cache/xip_cache.c
@@ -0,0 +1,109 @@
+#include "hardware/xip_cache.h"
+#include "hardware/structs/xip.h"
+// For barrier macros:
+#include "hardware/sync.h"
+
+// Implementation-private constants (exporting these would create a compatibility headache as they
+// don't exist on all platforms; all of these operations are exposed through APIs anyways)
+
+#if !PICO_RP2040
+typedef enum {
+ XIP_CACHE_INVALIDATE_BY_SET_WAY = 0,
+ XIP_CACHE_CLEAN_BY_SET_WAY = 1,
+ XIP_CACHE_INVALIDATE_BY_ADDRESS = 2,
+ XIP_CACHE_CLEAN_BY_ADDRESS = 3,
+ XIP_CACHE_PIN_AT_ADDRESS = 7,
+ XIP_CACHE_OP_MAX = 7
+} cache_op_t;
+#endif
+
+// Used to ensure subsequent accesses observe the new state of the maintained cache lines
+#define __post_maintenance_barrier() do {__dsb(); __isb();} while (0)
+
+// All functions in this file are marked non-flash, even though they themselves may be executed
+// safely from flash, because they are likely to be called during a flash programming operation
+// (which makes flash execution momentarily unsafe)
+
+__force_inline static void check_xip_offset_range(uintptr_t start_offset, uintptr_t size_bytes) {
+ // We use offsets, not addresses, for consistency with the flash API. This means the range of
+ // valid inputs starts at 0.
+ (void)start_offset;
+ (void)size_bytes;
+ valid_params_if(HARDWARE_XIP_CACHE, start_offset <= XIP_CACHE_ADDRESS_SPACE_SIZE);
+ valid_params_if(HARDWARE_XIP_CACHE, start_offset + size_bytes <= XIP_CACHE_ADDRESS_SPACE_SIZE);
+ // Check for unsigned wrapping too:
+ valid_params_if(HARDWARE_XIP_CACHE, start_offset + size_bytes >= start_offset);
+}
+
+#if !PICO_RP2040
+// Generic code for RP2350-style caches: apply a maintenance operation to a range of offsets
+static void __no_inline_not_in_flash_func(xip_cache_maintain)(uintptr_t start_offset, uintptr_t size_bytes, cache_op_t op) {
+ check_xip_offset_range(start_offset, size_bytes);
+ valid_params_if(HARDWARE_XIP_CACHE, (start_offset & (XIP_CACHE_LINE_SIZE - 1u)) == 0);
+ valid_params_if(HARDWARE_XIP_CACHE, (size_bytes & (XIP_CACHE_LINE_SIZE - 1u)) == 0);
+ valid_params_if(HARDWARE_XIP_CACHE, (uint)op <= (uint)XIP_CACHE_OP_MAX);
+
+ uintptr_t end = start_offset + size_bytes;
+ for (uintptr_t offset = start_offset; offset < end; offset += XIP_CACHE_LINE_SIZE) {
+ *(io_wo_8 *) (XIP_MAINTENANCE_BASE + offset + (uintptr_t)op) = 0;
+ }
+ __post_maintenance_barrier();
+}
+#endif
+
+void __no_inline_not_in_flash_func(xip_cache_invalidate_all)(void) {
+#if PICO_RP2040
+ xip_ctrl_hw->flush = 1;
+ // Read back to wait for completion
+ (void)xip_ctrl_hw->flush;
+ __post_maintenance_barrier();
+#else
+ xip_cache_maintain(XIP_CACHE_ADDRESS_SPACE_SIZE - XIP_CACHE_SIZE, XIP_CACHE_SIZE, XIP_CACHE_INVALIDATE_BY_SET_WAY);
+#endif
+}
+
+void __no_inline_not_in_flash_func(xip_cache_invalidate_range)(uintptr_t start_offset, uintptr_t size_bytes) {
+#if PICO_RP2040
+ // Accsses are at intervals of one half cache line (so 4 bytes) because RP2040's cache has two
+ // valid flags per cache line, and we need to clear both.
+ check_xip_offset_range(start_offset, size_bytes);
+ valid_params_if(HARDWARE_XIP_CACHE, (start_offset & 3u) == 0);
+ valid_params_if(HARDWARE_XIP_CACHE, (size_bytes & 3u) == 0);
+
+ uintptr_t end = start_offset + size_bytes;
+ // On RP2040 you can invalidate a sector (half-line) by writing to its normal cached+allocating address
+ for (uintptr_t offset = start_offset; offset < end; offset += 4u) {
+ *(io_wo_32 *)(offset + XIP_BASE) = 0;
+ }
+ __post_maintenance_barrier();
+
+#else
+
+ xip_cache_maintain(start_offset, size_bytes, XIP_CACHE_INVALIDATE_BY_ADDRESS);
+
+#endif
+}
+
+#if !XIP_CACHE_IS_READ_ONLY
+void __no_inline_not_in_flash_func(xip_cache_clean_all)(void) {
+ // Use addresses outside of the downstream QMI address range to work around RP2350-E11; this
+ // effectively performs a clean+invalidate (except being a no-op on pinned lines) due to the
+ // erroneous update of the tag. Consequently you will take a miss on the next access to the
+ // cleaned address.
+ xip_cache_maintain(XIP_END - XIP_BASE - XIP_CACHE_SIZE, XIP_CACHE_SIZE, XIP_CACHE_CLEAN_BY_SET_WAY);
+}
+#endif
+
+#if !XIP_CACHE_IS_READ_ONLY
+void __no_inline_not_in_flash_func(xip_cache_clean_range)(uintptr_t start_offset, uintptr_t size_bytes) {
+ xip_cache_maintain(start_offset, size_bytes, XIP_CACHE_CLEAN_BY_ADDRESS);
+}
+#endif
+
+#if !PICO_RP2040
+void __no_inline_not_in_flash_func(xip_cache_pin_range)(uintptr_t start_offset, uintptr_t size_bytes) {
+ valid_params_if(HARDWARE_XIP_CACHE, size_bytes <= XIP_CACHE_SIZE);
+ xip_cache_maintain(start_offset, size_bytes, XIP_CACHE_PIN_AT_ADDRESS);
+}
+#endif
+
diff --git a/src/rp2_common/pico_aon_timer/aon_timer.c b/src/rp2_common/pico_aon_timer/aon_timer.c
index 35173cf89..a4d594f63 100644
--- a/src/rp2_common/pico_aon_timer/aon_timer.c
+++ b/src/rp2_common/pico_aon_timer/aon_timer.c
@@ -13,6 +13,7 @@ static aon_timer_alarm_handler_t aon_timer_alarm_handler;
#if HAS_RP2040_RTC
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
+
#elif HAS_POWMAN_TIMER
#include "hardware/powman.h"
@@ -23,56 +24,92 @@ static void powman_timer_irq_handler(void) {
irq_remove_handler(irq_num, powman_timer_irq_handler);
if (aon_timer_alarm_handler) aon_timer_alarm_handler();
}
+
+static bool ts_to_tm(const struct timespec *ts, struct tm *tm) {
+ return pico_localtime_r(&ts->tv_sec, tm) != NULL;
+}
#endif
-void aon_timer_set_time(const struct timespec *ts) {
+static bool tm_to_ts(const struct tm *tm, struct timespec *ts) {
+ struct tm tm_clone = *tm;
+ ts->tv_sec = pico_mktime(&tm_clone);
+ ts->tv_nsec = 0;
+ return ts->tv_sec != -1;
+}
+
+bool aon_timer_set_time(const struct timespec *ts) {
#if HAS_RP2040_RTC
- datetime_t dt;
- bool ok = time_to_datetime(ts->tv_sec, &dt);
- assert(ok);
- if (ok) rtc_set_datetime(&dt);
+ struct tm tm;
+ bool ok = pico_localtime_r(&ts->tv_sec, &tm);
+ if (ok) aon_timer_set_time_calendar(&tm);
+ return ok;
#elif HAS_POWMAN_TIMER
powman_timer_set_ms(timespec_to_ms(ts));
+ return true;
#else
panic_unsupported();
#endif
}
-void aon_timer_get_time(struct timespec *ts) {
+bool aon_timer_set_time_calendar(const struct tm *tm) {
#if HAS_RP2040_RTC
datetime_t dt;
- rtc_get_datetime(&dt);
- time_t t;
- bool ok = datetime_to_time(&dt, &t);
- assert(ok);
- ts->tv_nsec = 0;
- if (ok) {
- ts->tv_sec = t;
- } else {
- ts->tv_sec = -1;
+ tm_to_datetime(tm, &dt);
+ rtc_set_datetime(&dt);
+ return true;
+#elif HAS_POWMAN_TIMER
+ struct timespec ts;
+ if (tm_to_ts(tm, &ts)) {
+ return aon_timer_set_time(&ts);
}
+ return false;
+#else
+ panic_unsupported();
+#endif
+}
+
+bool aon_timer_get_time(struct timespec *ts) {
+#if HAS_RP2040_RTC
+ struct tm tm;
+ bool ok = aon_timer_get_time_calendar(&tm);
+ return ok && tm_to_ts(&tm, ts);
#elif HAS_POWMAN_TIMER
ms_to_timespec(powman_timer_get_ms(), ts);
+ return true;
#else
panic_unsupported();
#endif
}
-aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power) {
- uint32_t save = save_and_disable_interrupts();
- aon_timer_alarm_handler_t old_handler = aon_timer_alarm_handler;
- struct timespec ts_adjusted = *ts;
+bool aon_timer_get_time_calendar(struct tm *tm) {
#if HAS_RP2040_RTC
- ((void)wakeup_from_low_power); // don't have a choice
datetime_t dt;
+ rtc_get_datetime(&dt);
+ datetime_to_tm(&dt, tm);
+ return true;
+#elif HAS_POWMAN_TIMER
+ struct timespec ts;
+ aon_timer_get_time(&ts);
+ return ts_to_tm(&ts, tm);
+#else
+ panic_unsupported();
+#endif
+}
+
+aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power) {
+#if HAS_RP2040_RTC
+ struct tm tm;
// adjust to after the target time
+ struct timespec ts_adjusted = *ts;
if (ts_adjusted.tv_nsec) ts_adjusted.tv_sec++;
- bool ok = time_to_datetime(ts_adjusted.tv_sec, &dt);
- assert(ok);
- if (ok) {
- rtc_set_alarm(&dt, handler);
+ if (!pico_localtime_r(&ts_adjusted.tv_sec, &tm)) {
+ return (aon_timer_alarm_handler_t)PICO_ERROR_INVALID_ARG;
}
+ return aon_timer_enable_alarm_calendar(&tm, handler, wakeup_from_low_power);
#elif HAS_POWMAN_TIMER
+ uint32_t save = save_and_disable_interrupts();
+ aon_timer_alarm_handler_t old_handler = aon_timer_alarm_handler;
+ struct timespec ts_adjusted = *ts;
uint irq_num = aon_timer_get_irq_num();
powman_timer_disable_alarm();
// adjust to after the target time
@@ -92,12 +129,34 @@ aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_
irq_set_exclusive_handler(irq_num, powman_timer_irq_handler);
irq_set_enabled(irq_num, true);
}
+ aon_timer_alarm_handler = handler;
+ restore_interrupts_from_disabled(save);
+ return old_handler;
#else
panic_unsupported();
#endif
+}
+
+aon_timer_alarm_handler_t aon_timer_enable_alarm_calendar(const struct tm *tm, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power) {
+#if HAS_RP2040_RTC
+ ((void)wakeup_from_low_power); // don't have a choice
+ uint32_t save = save_and_disable_interrupts();
+ aon_timer_alarm_handler_t old_handler = aon_timer_alarm_handler;
+ datetime_t dt;
+ tm_to_datetime(tm, &dt);
+ rtc_set_alarm(&dt, handler);
aon_timer_alarm_handler = handler;
restore_interrupts_from_disabled(save);
return old_handler;
+#elif HAS_POWMAN_TIMER
+ struct timespec ts;
+ if (!tm_to_ts(tm, &ts)) {
+ return (aon_timer_alarm_handler_t)PICO_ERROR_INVALID_ARG;
+ }
+ return aon_timer_enable_alarm(&ts, handler, wakeup_from_low_power);
+#else
+ panic_unsupported();
+#endif
}
void aon_timer_disable_alarm(void) {
@@ -120,15 +179,36 @@ void aon_timer_start_with_timeofday(void) {
aon_timer_start(&ts);
}
-void aon_timer_start(const struct timespec *ts) {
+bool aon_timer_start(const struct timespec *ts) {
#if HAS_RP2040_RTC
rtc_init();
- aon_timer_set_time(ts);
+ return aon_timer_set_time(ts);
#elif HAS_POWMAN_TIMER
// todo how best to allow different configurations; this should just be the default
powman_timer_set_1khz_tick_source_xosc();
- powman_timer_set_ms(timespec_to_ms(ts));
- powman_timer_start();
+ bool ok = aon_timer_set_time(ts);
+ if (ok) {
+ powman_timer_set_ms(timespec_to_ms(ts));
+ powman_timer_start();
+ }
+ return ok;
+#else
+ panic_unsupported();
+#endif
+}
+
+bool aon_timer_start_calendar(const struct tm *tm) {
+#if HAS_RP2040_RTC
+ rtc_init();
+ return aon_timer_set_time_calendar(tm);
+#elif HAS_POWMAN_TIMER
+ // todo how best to allow different configurations; this should just be the default
+ powman_timer_set_1khz_tick_source_xosc();
+ bool ok = aon_timer_set_time_calendar(tm);
+ if (ok) {
+ powman_timer_start();
+ }
+ return ok;
#else
panic_unsupported();
#endif
diff --git a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h
index d3f69ade9..768c79827 100644
--- a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h
+++ b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h
@@ -21,7 +21,39 @@
* This library uses the RTC on RP2040.
* \endif
* \if rp2350_specific
- * This library uses the RTC on RP2350.
+ * This library uses the Powman Timer on RP2350.
+ * \endif
+ *
+ * This library supports both `aon_timer_xxx_calendar()` methods which use a calendar date/time (as struct tm),
+ * and `aon_timer_xxx()` methods which use a linear time value relative an internal reference time (via struct timespec).
+ *
+ * \if rp2040_specific
+ * \anchor rp2040_caveats
+ * On RP2040 the non 'calendar date/time' methods must convert the linear time value to a calendar date/time internally; these methods are:
+ *
+ * * \ref aon_timer_start_with_timeofday
+ * * \ref aon_timer_start
+ * * \ref aon_timer_set_time
+ * * \ref aon_timer_get_time
+ * * \ref aon_timer_enable_alarm
+ *
+ * This conversion is handled by the \ref pico_localtime_r method. By default, this pulls in the C library `local_time_r` method
+ * which can lead to a big increase in binary size. The default implementation of `pico_localtime_r` is weak, so it can be overridden
+ * if a better/smaller alternative is available, otherwise you might consider the method variants ending in `_calendar()` instead on RP2040.
+ * \endif
+ *
+ * \if rp2350_specific
+ * \anchor rp2350_caveats
+ * On RP2350 the 'calendar date/time' methods must convert the calendar date/time to a linear time value internally; these methods are:
+ *
+ * * \ref aon_timer_start_calendar
+ * * \ref aon_timer_set_time_calendar
+ * * \ref aon_timer_get_time_calendar
+ * * \ref aon_timer_enable_alarm_calendar
+ *
+ * This conversion is handled by the \ref pico_mktime method. By default, this pulls in the C library `mktime` method
+ * which can lead to a big increase in binary size. The default implementation of `pico_mktime` is weak, so it can be overridden
+ * if a better/smaller alternative is available, otherwise you might consider the method variants not ending in `_calendar()` instead on RP2350.
* \endif
*/
@@ -49,6 +81,11 @@ typedef void (*aon_timer_alarm_handler_t)(void);
/**
* \brief Start the AON timer running using the result from the gettimeofday() function as the current time
+ *
+ * \if rp2040_specific
+ * See \ref rp2040_caveats "caveats" for using this method on RP2040
+ * \endif
+ *
* \ingroup pico_aon_timer
*/
void aon_timer_start_with_timeofday(void);
@@ -56,9 +93,30 @@ void aon_timer_start_with_timeofday(void);
/**
* \brief Start the AON timer running using the specified timespec as the current time
* \ingroup pico_aon_timer
- * \param ts the current time
+ *
+ * \if rp2040_specific
+ * See \ref rp2040_caveats "caveats" for using this method on RP2040
+ * \endif
+ *
+ * \param ts the time to set as 'now'
+ * \return true on success, false if internal time format conversion failed
+ * \sa aon_timer_start_calendar
+ */
+bool aon_timer_start(const struct timespec *ts);
+
+/**
+ * \brief Start the AON timer running using the specified calendar date/time as the current time
+ *
+ * \if rp2350_specific
+ * See \ref rp2350_caveats "caveats" for using this method on RP2350
+ * \endif
+ *
+ * \ingroup pico_aon_timer
+ * \param tm the calendar date/time to set as 'now'
+ * \return true on success, false if internal time format conversion failed
+ * \sa aon_timer_start
*/
-void aon_timer_start(const struct timespec *ts);
+bool aon_timer_start_calendar(const struct tm *tm);
/**
* \brief Stop the AON timer
@@ -67,18 +125,60 @@ void aon_timer_start(const struct timespec *ts);
void aon_timer_stop(void);
/**
- * \brief Update the current time of the AON timer
+ * \brief Set the current time of the AON timer
* \ingroup pico_aon_timer
+ *
+ * \if rp2040_specific
+ * See \ref rp2040_caveats "caveats" for using this method on RP2040
+ * \endif
+ *
* \param ts the new current time
+ * \return true on success, false if internal time format conversion failed
+ * \sa aon_timer_set_time_calendar
+ */
+bool aon_timer_set_time(const struct timespec *ts);
+
+/**
+ * \brief Set the current time of the AON timer to the given calendar date/time
+ * \ingroup pico_aon_timer
+ *
+ * \if rp2350_specific
+ * See \ref rp2350_caveats "caveats" for using this method on RP2350
+ * \endif
+ *
+ * \param tm the new current time
+ * \return true on success, false if internal time format conversion failed
+ * \sa aon_timer_set_time
*/
-void aon_timer_set_time(const struct timespec *ts);
+bool aon_timer_set_time_calendar(const struct tm *tm);
/**
* \brief Get the current time of the AON timer
* \ingroup pico_aon_timer
+ *
+ * \if rp2040_specific
+ * See \ref rp2040_caveats "caveats" for using this method on RP2040
+ * \endif
+ *
* \param ts out value for the current time
+ * \return true on success, false if internal time format conversion failed
+ * \sa aon_timer_get_time_calendar
*/
-void aon_timer_get_time(struct timespec *ts);
+bool aon_timer_get_time(struct timespec *ts);
+
+ /**
+ * \brief Get the current time of the AON timer as a calendar date/time
+ * \ingroup pico_aon_timer
+ *
+ * \if rp2350_specific
+ * See \ref rp2350_caveats "caveats" for using this method on RP2350
+ * \endif
+ *
+ * \param tm out value for the current calendar date/time
+ * \return true on success, false if internal time format conversion failed
+ * \sa aon_timer_get_time
+ */
+bool aon_timer_get_time_calendar(struct tm *tm);
/**
* \brief Get the resolution of the AON timer
@@ -88,22 +188,50 @@ void aon_timer_get_time(struct timespec *ts);
void aon_timer_get_resolution(struct timespec *ts);
/**
- * \brief Enable an AON timer alarm for a specifed time
+ * \brief Enable an AON timer alarm for a specified time
* \ingroup pico_aon_timer
*
- * \if rp2040_specific
- * On RP2040 The alarm will not fire if it is in the past
- * \endif
* \if rp2350_specific
- * On RP2040 The alarm will fire if it is in the past
+ * On RP2350 the alarm will fire if it is in the past
+ * \endif
+ * \if rp2040_specific
+ * On RP2040 the alarm will not fire if it is in the past.
+ *
+ * See \ref rp2040_caveats "caveats" for using this method on RP2040
* \endif
*
* \param ts the alarm time
- * \param handler a callback to call when the timer fires (may be NULL for wakeup_from_low_power = true)
+ * \param handler a callback to call when the timer fires (can be NULL for wakeup_from_low_power = true)
* \param wakeup_from_low_power true if the AON timer is to be used to wake up from a DORMANT state
+ * \return on success the old handler (or NULL if there was none)
+ * or PICO_ERROR_INVALID_ARG if internal time format conversion failed
+ * \sa pico_localtime_r
*/
aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power);
+/**
+ * \brief Enable an AON timer alarm for a specified calendar date/time
+ * \ingroup pico_aon_timer
+ *
+ * \if rp2350_specific
+ * On RP2350 the alarm will fire if it is in the past
+ *
+ * See \ref rp2350_caveats "caveats" for using this method on RP2350
+ * \endif
+ *
+ * \if rp2040_specific
+ * On RP2040 the alarm will not fire if it is in the past.
+ * \endif
+ *
+ * \param tm the alarm calendar date/time
+ * \param handler a callback to call when the timer fires (can be NULL for wakeup_from_low_power = true)
+ * \param wakeup_from_low_power true if the AON timer is to be used to wake up from a DORMANT state
+ * \return on success the old handler (or NULL if there was none)
+ * or PICO_ERROR_INVALID_ARG if internal time format conversion failed
+ * \sa pico_localtime_r
+ */
+aon_timer_alarm_handler_t aon_timer_enable_alarm_calendar(const struct tm *tm, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power);
+
/**
* \brief Disable the currently enabled AON timer alarm if any
* \ingroup pico_aon_timer
diff --git a/src/rp2_common/pico_async_context/BUILD.bazel b/src/rp2_common/pico_async_context/BUILD.bazel
index 8d57b52fc..a2de0acd2 100644
--- a/src/rp2_common/pico_async_context/BUILD.bazel
+++ b/src/rp2_common/pico_async_context/BUILD.bazel
@@ -2,8 +2,18 @@ load("//bazel:defs.bzl", "compatible_with_rp2", "incompatible_with_config")
package(default_visibility = ["//visibility:public"])
-cc_library(
+alias(
name = "pico_async_context",
+ actual = select({
+ "//bazel/constraint:pico_async_context_poll_enabled": ":pico_async_context_poll",
+ "//bazel/constraint:pico_async_context_threadsafe_background_enabled": ":pico_async_context_threadsafe_background",
+ "//bazel/constraint:pico_async_context_freertos_enabled": ":pico_async_context_freertos",
+ "//conditions:default": "//bazel:incompatible_cc_lib",
+ }),
+)
+
+cc_library(
+ name = "pico_async_context_base",
srcs = ["async_context_base.c"],
hdrs = [
"include/pico/async_context.h",
@@ -26,7 +36,7 @@ cc_library(
"//bazel/constraint:pico_freertos_unset",
),
deps = [
- ":pico_async_context",
+ ":pico_async_context_base",
"//bazel/config:PICO_FREERTOS_LIB",
"//src/common/pico_sync",
"//src/common/pico_time",
@@ -42,7 +52,7 @@ cc_library(
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
- ":pico_async_context",
+ ":pico_async_context_base",
"//src/common/pico_sync",
"//src/common/pico_time",
"//src/rp2_common:pico_platform",
@@ -56,7 +66,7 @@ cc_library(
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
- ":pico_async_context",
+ ":pico_async_context_base",
"//src/common/pico_sync",
"//src/common/pico_time",
"//src/rp2_common:pico_platform",
diff --git a/src/rp2_common/pico_async_context/async_context_freertos.c b/src/rp2_common/pico_async_context/async_context_freertos.c
index a4304d476..3cffcbb98 100644
--- a/src/rp2_common/pico_async_context/async_context_freertos.c
+++ b/src/rp2_common/pico_async_context/async_context_freertos.c
@@ -188,7 +188,6 @@ static void handle_sync_func_call(async_context_t *context, async_when_pending_w
sync_func_call_t *call = (sync_func_call_t *)worker;
call->rc = call->func(call->param);
xSemaphoreGive(call->sem);
- async_context_remove_when_pending_worker(context, worker);
}
uint32_t async_context_freertos_execute_sync(async_context_t *self_base, uint32_t (*func)(void *param), void *param) {
@@ -202,6 +201,7 @@ uint32_t async_context_freertos_execute_sync(async_context_t *self_base, uint32_
async_context_add_when_pending_worker(self_base, &call.worker);
async_context_set_work_pending(self_base, &call.worker);
xSemaphoreTake(call.sem, portMAX_DELAY);
+ async_context_remove_when_pending_worker(self_base, &call.worker);
vSemaphoreDelete(call.sem);
return call.rc;
}
diff --git a/src/rp2_common/pico_atomic/atomic.c b/src/rp2_common/pico_atomic/atomic.c
index e318356e5..2bbf3cdbd 100644
--- a/src/rp2_common/pico_atomic/atomic.c
+++ b/src/rp2_common/pico_atomic/atomic.c
@@ -12,14 +12,11 @@
#define memcmp __builtin_memcmp
static inline uint32_t atomic_lock(__unused const volatile void *ptr) {
- uint32_t save = save_and_disable_interrupts();
-// __dmb(); not necessary on RP2040
- return save;
+ return spin_lock_blocking(spin_lock_instance(PICO_SPINLOCK_ID_ATOMIC));
}
static inline void atomic_unlock(__unused const volatile void *ptr, uint32_t save) {
-// __dmb(); not necessary on RP2040
- restore_interrupts_from_disabled(save);
+ spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_ATOMIC), save);
}
#if PICO_C_COMPILER_IS_GNU
diff --git a/src/rp2_common/pico_bit_ops/BUILD.bazel b/src/rp2_common/pico_bit_ops/BUILD.bazel
index 66af3fd9e..dcfe1a674 100644
--- a/src/rp2_common/pico_bit_ops/BUILD.bazel
+++ b/src/rp2_common/pico_bit_ops/BUILD.bazel
@@ -25,6 +25,7 @@ cc_library(
"//src/common/pico_bit_ops_headers:pico_bit_ops_interface",
"//src/rp2_common:pico_platform_internal",
"//src/rp2_common/pico_bootrom",
+ "//src/rp2_common/pico_runtime_init",
],
alwayslink = True, # Ensures the wrapped symbols are linked in.
)
diff --git a/src/rp2_common/pico_bootrom/BUILD.bazel b/src/rp2_common/pico_bootrom/BUILD.bazel
index 5a7060938..53a24b105 100644
--- a/src/rp2_common/pico_bootrom/BUILD.bazel
+++ b/src/rp2_common/pico_bootrom/BUILD.bazel
@@ -2,7 +2,7 @@ load("//bazel:defs.bzl", "compatible_with_rp2")
package(default_visibility = ["//visibility:public"])
-# Picotool needs this, so we can't strictly constrain compatibility.
+# Picotool needs this, so we can't strictly constrain platform compatibility.
cc_library(
name = "pico_bootrom_headers",
hdrs = [
@@ -15,8 +15,13 @@ cc_library(
tags = ["manual"],
visibility = ["@picotool//:__subpackages__"],
deps = [
+ "//src/rp2_common/boot_bootrom_headers",
"//src/rp2_common/hardware_boot_lock:hardware_boot_lock_headers",
- ],
+ "//src/rp2_common/pico_flash:pico_flash_headers",
+ ] + select({
+ "//bazel/constraint:host": ["//src/host/hardware_sync"],
+ "//conditions:default": ["//src/rp2_common/hardware_sync"],
+ }),
)
cc_library(
@@ -25,22 +30,15 @@ cc_library(
"bootrom.c",
"bootrom_lock.c",
],
- hdrs = [
- "include/pico/bootrom.h",
- "include/pico/bootrom/lock.h",
- "include/pico/bootrom/sf_table.h",
- "include/pico/bootrom_constants.h",
- ],
implementation_deps = [
"//src/common/boot_picobin_headers",
"//src/common/boot_picoboot_headers",
"//src/rp2_common/hardware_sync",
"//src/rp2_common/pico_runtime_init",
],
- includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
- "//src/rp2_common/hardware_boot_lock",
+ ":pico_bootrom_headers",
] + select({
"//bazel/constraint:host": [
],
diff --git a/src/rp2_common/pico_bootrom/CMakeLists.txt b/src/rp2_common/pico_bootrom/CMakeLists.txt
index 0648098b9..c7ac816f2 100644
--- a/src/rp2_common/pico_bootrom/CMakeLists.txt
+++ b/src/rp2_common/pico_bootrom/CMakeLists.txt
@@ -8,5 +8,9 @@ target_sources(pico_bootrom INTERFACE
${CMAKE_CURRENT_LIST_DIR}/bootrom_lock.c
)
-target_link_libraries(pico_bootrom_headers INTERFACE boot_picoboot_headers)
-pico_mirrored_target_link_libraries(pico_bootrom INTERFACE pico_base hardware_boot_lock)
+target_link_libraries(pico_bootrom_headers INTERFACE boot_picoboot_headers boot_bootrom_headers)
+pico_mirrored_target_link_libraries(pico_bootrom INTERFACE pico_base hardware_boot_lock pico_flash)
+
+# bootrom.c includes boot/picobin.h
+# bootrom_lock.c includes pico/runtime_init.h
+target_link_libraries(pico_bootrom INTERFACE boot_picobin_headers pico_runtime_init_headers)
\ No newline at end of file
diff --git a/src/rp2_common/pico_bootrom/bootrom.c b/src/rp2_common/pico_bootrom/bootrom.c
index 84fbffd06..344e3724c 100644
--- a/src/rp2_common/pico_bootrom/bootrom.c
+++ b/src/rp2_common/pico_bootrom/bootrom.c
@@ -22,8 +22,13 @@ void *rom_data_lookup(uint32_t code) {
rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET);
uint16_t *data_table = (uint16_t *) rom_hword_as_ptr(BOOTROM_DATA_TABLE_OFFSET);
return rom_table_lookup(data_table, code);
+#else
+#ifdef __riscv
+ uint32_t rom_offset_adjust = rom_size_is_64k() ? 32 * 1024 : 0;
+ rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_OFFSET + rom_offset_adjust);
#else
rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_OFFSET);
+#endif
return rom_table_lookup(code, RT_FLAG_DATA);
#endif
}
@@ -58,6 +63,26 @@ void __attribute__((noreturn)) rom_reset_usb_boot(uint32_t usb_activity_gpio_pin
#endif
}
+void __attribute__((noreturn)) rom_reset_usb_boot_extra(int usb_activity_gpio_pin, uint32_t disable_interface_mask, bool usb_activity_gpio_pin_active_low) {
+#ifdef ROM_FUNC_RESET_USB_BOOT
+ (void)usb_activity_gpio_pin_active_low;
+ rom_reset_usb_boot_fn func = (rom_reset_usb_boot_fn) rom_func_lookup(ROM_FUNC_RESET_USB_BOOT);
+ func(usb_activity_gpio_pin < 0 ? 0 : (1u << usb_activity_gpio_pin), disable_interface_mask);
+#elif defined(ROM_FUNC_REBOOT)
+ uint32_t flags = disable_interface_mask;
+ if (usb_activity_gpio_pin >= 0) {
+ flags |= BOOTSEL_FLAG_GPIO_PIN_SPECIFIED;
+ if (usb_activity_gpio_pin_active_low) {
+ flags |= BOOTSEL_FLAG_GPIO_PIN_ACTIVE_LOW;
+ }
+ }
+ rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, (uint)usb_activity_gpio_pin);
+ __builtin_unreachable();
+#else
+ panic_unsupported();
+#endif
+}
+
#if !PICO_RP2040
bool rom_get_boot_random(uint32_t out[4]) {
uint32_t result[5];
diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom.h b/src/rp2_common/pico_bootrom/include/pico/bootrom.h
index b55e0988a..498d4f724 100644
--- a/src/rp2_common/pico_bootrom/include/pico/bootrom.h
+++ b/src/rp2_common/pico_bootrom/include/pico/bootrom.h
@@ -20,6 +20,7 @@
#ifndef __ASSEMBLER__
#include
#include "pico/bootrom/lock.h"
+#include "pico/flash.h"
// ROM FUNCTION SIGNATURES
#if PICO_RP2040
@@ -173,32 +174,7 @@ __force_inline static void *rom_hword_as_ptr(uint16_t rom_address) {
#ifdef __riscv
static __force_inline bool rom_size_is_64k(void) {
#ifdef RASPBERRYPI_AMETHYST_FPGA
- // Detect ROM size by testing for bus fault at +32k
- uint result;
- pico_default_asm_volatile (
- "li %0, 0\n"
- // Save and disable IRQs before touching trap vector
- "csrr t2, mstatus\n"
- "csrci mstatus, 0x8\n"
- // Set up trap vector to skip the instruction which sets the %0 flag
- "la t0, 1f\n"
- "csrrw t0, mtvec, t0\n"
- // This load will fault if the bootrom is no larger than 32k:
- "li t1, 32 * 1024\n"
- "lw t1, (t1)\n"
- // No fault, so set return to true
- "li %0, 1\n"
- ".p2align 2\n"
- // Always end up back here, restore the trap table
- "1:\n"
- "csrw mtvec, t0\n"
- // Now safe to restore interrupts
- "csrw mstatus, t2\n"
- : "=r" (result)
- :
- : "t0", "t1", "t2"
- );
- return result;
+ return *(uint16_t*)0x14 >= 0x8000;
#else
return false;
#endif
@@ -261,6 +237,25 @@ static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activit
rom_reset_usb_boot(usb_activity_gpio_pin_mask, disable_interface_mask);
}
+/*!
+ * \brief Reboot the device into BOOTSEL mode
+ * \ingroup pico_bootrom
+ *
+ * This function reboots the device into the BOOTSEL mode ('usb boot").
+ *
+ * Facilities are provided to enable an "activity light" via GPIO attached LED for the USB Mass Storage Device,
+ * and to limit the USB interfaces exposed.
+ *
+ * \param usb_activity_gpio_pin GPIO pin to be used as an activitiy pin, or -1 for none
+ * from the host.
+ * \param disable_interface_mask value to control exposed interfaces
+ * - 0 To enable both interfaces (as per a cold boot)
+ * - 1 To disable the USB Mass Storage Interface
+ * - 2 To disable the USB PICOBOOT Interface
+ * \param usb_activity_gpio_pin_active_low Activity GPIO is active low (ignored on RP2040)
+ */
+void __attribute__((noreturn)) rom_reset_usb_boot_extra(int usb_activity_gpio_pin, uint32_t disable_interface_mask, bool usb_activity_gpio_pin_active_low);
+
/*!
* \brief Connect the SSI/QMI to the QSPI pads
* \ingroup pico_bootrom
@@ -273,7 +268,7 @@ static inline void __attribute__((noreturn)) reset_usb_boot(uint32_t usb_activit
* bank 0 IOs are untouched.
* \endif
*/
-static inline void rom_connect_internal_flash() {
+static inline void rom_connect_internal_flash(void) {
rom_connect_internal_flash_fn func = (rom_connect_internal_flash_fn) rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);
func();
}
@@ -304,7 +299,7 @@ static inline void rom_connect_internal_flash() {
* device from its XIP state to a serial command state.
* \endif
*/
-static inline void rom_flash_exit_xip() {
+static inline void rom_flash_exit_xip(void) {
rom_flash_exit_xip_fn func = (rom_flash_exit_xip_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);
func();
}
@@ -387,7 +382,7 @@ static inline void rom_flash_range_program(uint32_t addr, const uint8_t *data, s
* No other operations are performed.
* \endif
*/
-static inline void rom_flash_flush_cache() {
+static inline void rom_flash_flush_cache(void) {
rom_flash_flush_cache_fn func = (rom_flash_flush_cache_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
func();
}
@@ -403,7 +398,7 @@ static inline void rom_flash_flush_cache() {
* Note that the same setup is performed by flash_exit_xip(), and the RP2350 flash program/erase functions do not leave XIP in an
* inaccessible state, so calls to this function are largely redundant on RP2350. It is provided on RP2350 for compatibility with RP2040.
*/
-static inline void rom_flash_enter_cmd_xip() {
+static inline void rom_flash_enter_cmd_xip(void) {
rom_flash_enter_cmd_xip_fn func = (rom_flash_enter_cmd_xip_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_ENTER_CMD_XIP);
func();
}
@@ -542,6 +537,20 @@ static inline void rom_flash_select_xip_read_mode(bootrom_xip_mode_t mode, uint8
func(mode, clkdiv);
}
+typedef struct {
+ cflash_flags_t flags;
+ uintptr_t addr;
+ uint32_t size_bytes;
+ uint8_t *buf;
+ int *res;
+} rom_helper_flash_op_params_t;
+
+static inline void rom_helper_flash_op(void *param) {
+ const rom_helper_flash_op_params_t *op = (const rom_helper_flash_op_params_t *)param;
+ rom_flash_op_fn func = (rom_flash_op_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_OP);
+ *(op->res) = func(op->flags, op->addr, op->size_bytes, op->buf);
+}
+
/*!
* \brief Perform a flash read, erase, or program operation
* \ingroup pico_bootrom
@@ -582,12 +591,23 @@ static inline void rom_flash_select_xip_read_mode(bootrom_xip_mode_t mode, uint8
* \param buf contains data to be written to flash, for program operations, and data read back from flash, for read operations
*/
static inline int rom_flash_op(cflash_flags_t flags, uintptr_t addr, uint32_t size_bytes, uint8_t *buf) {
- rom_flash_op_fn func = (rom_flash_op_fn) rom_func_lookup_inline(ROM_FUNC_FLASH_OP);
if (!bootrom_try_acquire_lock(BOOTROM_LOCK_FLASH_OP))
return BOOTROM_ERROR_LOCK_REQUIRED;
- int rc = func(flags, addr, size_bytes, buf);
+ int rc = 0;
+ rom_helper_flash_op_params_t params = {
+ .flags = flags,
+ .addr = addr,
+ .size_bytes = size_bytes,
+ .buf = buf,
+ .res = &rc
+ };
+ int flash_rc = flash_safe_execute(rom_helper_flash_op, ¶ms, UINT32_MAX);
bootrom_release_lock(BOOTROM_LOCK_FLASH_OP);
- return rc;
+ if (flash_rc != PICO_OK) {
+ return flash_rc;
+ } else {
+ return rc;
+ }
}
/*!
@@ -639,7 +659,7 @@ static inline int rom_func_otp_access(uint8_t *buf, uint32_t buf_len, otp_cmd_t
* a hash of the partition table as of the time it loaded it. If the hash has changed by the time this method is called,
* then it will return BOOTROM_ERROR_INVALID_STATE.
*
- * The information returned is chosen by the flags_and_partition parameter; the first word in the returned buffer,
+ * The information returned is chosen by the partition_and_flags parameter; the first word in the returned buffer,
* is the (sub)set of those flags that the API supports. You should always check this value before interpreting
* the buffer.
*
@@ -667,7 +687,7 @@ static inline int rom_get_partition_table_info(uint32_t *out_buffer, uint32_t ou
*
* This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
* As a result it requires a user provided memory buffer as a work area. The work area should byte word-aligned and of sufficient size
- * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3064, so 3K is a good choice.
+ * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
*
* If force_reload is false, then this method will return BOOTROM_OK immediately if the bootrom is loaded, otherwise it will
* reload the partition table if it has been loaded already, allowing for the partition table to be updated in a running program.
@@ -694,7 +714,7 @@ static inline int rom_load_partition_table(uint8_t *workarea_base, uint32_t work
*
* This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
* As a result it requires a user provided memory buffer as a work area. The work area should bye word aligned, and of sufficient size
- * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3064, so 3K is a good choice.
+ * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
*
* The passed partition number can be any valid partition number other than the "B" partition of an A/B pair.
*
@@ -741,7 +761,7 @@ static inline int rom_get_b_partition(uint pi_a) {
*
* This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
* As a result it requires a user provided memory buffer as a work area. The work area should byte word-aligned and of sufficient size
- * or `BOOTROM_ERROR_INSUFFICIENT_RESOURCES` will be returned. The work area size currently required is 3064, so 3K is a good choice.
+ * or `BOOTROM_ERROR_INSUFFICIENT_RESOURCES` will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
*
* If the partition table
* has not been loaded (e.g. from a watchdog or RAM boot), then this method will return `BOOTROM_ERROR_PRECONDITION_NOT_MET`, and you
@@ -794,7 +814,7 @@ static inline intptr_t rom_flash_runtime_to_storage_addr(uintptr_t flash_runtime
*
* This method potentially requires similar complexity to the boot path in terms of picking amongst versions, checking signatures etc.
* As a result it requires a user provided memory buffer as a work area. The work area should be word aligned, and of sufficient size
- * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3064, so 3K is a good choice.
+ * or BOOTROM_ERROR_INSUFFICIENT_RESOURCES will be returned. The work area size currently required is 3264, so 3.25K is a good choice.
*
* NOTE: This method is primarily expected to be used when implementing bootloaders.
*
@@ -809,11 +829,25 @@ static inline intptr_t rom_flash_runtime_to_storage_addr(uintptr_t flash_runtime
static inline int rom_chain_image(uint8_t *workarea_base, uint32_t workarea_size, uint32_t region_base, uint32_t region_size) {
rom_chain_image_fn func = (rom_chain_image_fn) rom_func_lookup_inline(ROM_FUNC_CHAIN_IMAGE);
bootrom_release_lock(BOOTROM_LOCK_ENABLE);
+ uint32_t interrupt_flags = save_and_disable_interrupts();
int rc = func(workarea_base, workarea_size, region_base, region_size);
+ restore_interrupts_from_disabled(interrupt_flags);
bootrom_acquire_lock_blocking(BOOTROM_LOCK_ENABLE);
return rc;
}
+typedef struct {
+ uint8_t *buffer;
+ uint32_t buffer_size;
+ int *res;
+} rom_helper_explicit_buy_params_t;
+
+static inline void rom_helper_explicit_buy(void *param) {
+ const rom_helper_explicit_buy_params_t *op = (const rom_helper_explicit_buy_params_t *)param;
+ rom_explicit_buy_fn func = (rom_explicit_buy_fn) rom_func_lookup_inline(ROM_FUNC_EXPLICIT_BUY);
+ *(op->res) = func(op->buffer, op->buffer_size);
+}
+
// todo SECURE only
/*!
* \brief Buy an image
@@ -841,8 +875,18 @@ static inline int rom_chain_image(uint8_t *workarea_base, uint32_t workarea_size
* \param buffer_size size of scratch space
*/
static inline int rom_explicit_buy(uint8_t *buffer, uint32_t buffer_size) {
- rom_explicit_buy_fn func = (rom_explicit_buy_fn) rom_func_lookup_inline(ROM_FUNC_EXPLICIT_BUY);
- return func(buffer, buffer_size);
+ int rc = 0;
+ rom_helper_explicit_buy_params_t params = {
+ .buffer = buffer,
+ .buffer_size = buffer_size,
+ .res = &rc
+ };
+ int flash_rc = flash_safe_execute(rom_helper_explicit_buy, ¶ms, UINT32_MAX);
+ if (flash_rc != PICO_OK) {
+ return flash_rc;
+ } else {
+ return rc;
+ }
}
#ifndef __riscv
diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom/lock.h b/src/rp2_common/pico_bootrom/include/pico/bootrom/lock.h
index f436557fa..ff36eed37 100644
--- a/src/rp2_common/pico_bootrom/include/pico/bootrom/lock.h
+++ b/src/rp2_common/pico_bootrom/include/pico/bootrom/lock.h
@@ -10,7 +10,7 @@
#include "hardware/boot_lock.h"
#include "pico/bootrom_constants.h"
-// PICO_CONFIG: PICO_BOOTROM_LOCKING_ENABLED, Enable/disable locking for bootrom functions that use shared reqsources. If this flag is enabled bootrom lock checking is turned on and BOOT locks are taken around the relevant bootrom functions, type=bool, default=1, group=pico_bootrom
+// PICO_CONFIG: PICO_BOOTROM_LOCKING_ENABLED, Enable/disable locking for bootrom functions that use shared resources. If this flag is enabled bootrom lock checking is turned on and BOOT locks are taken around the relevant bootrom functions, type=bool, default=1, group=pico_bootrom
#ifndef PICO_BOOTROM_LOCKING_ENABLED
#if NUM_BOOT_LOCKS > 0
#define PICO_BOOTROM_LOCKING_ENABLED 1
diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom_constants.h b/src/rp2_common/pico_bootrom/include/pico/bootrom_constants.h
index 924487f8c..b3bfd47ea 100644
--- a/src/rp2_common/pico_bootrom/include/pico/bootrom_constants.h
+++ b/src/rp2_common/pico_bootrom/include/pico/bootrom_constants.h
@@ -4,339 +4,5 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef _PICO_BOOTROM_CONSTANTS_H
-#define _PICO_BOOTROM_CONSTANTS_H
-
-#ifndef NO_PICO_PLATFORM
-#include "pico/platform.h"
-#endif
-
-// ROOT ADDRESSES
-#define BOOTROM_MAGIC_OFFSET 0x10
-#define BOOTROM_FUNC_TABLE_OFFSET 0x14
-#if PICO_RP2040
-#define BOOTROM_DATA_TABLE_OFFSET 0x16
-#endif
-
-#if PICO_RP2040
-#define BOOTROM_VTABLE_OFFSET 0x00
-#define BOOTROM_TABLE_LOOKUP_OFFSET 0x18
-#else
-// todo remove this (or #ifdef it for A1/A2)
-#define BOOTROM_IS_A2() ((*(volatile uint8_t *)0x13) == 2)
-#define BOOTROM_WELL_KNOWN_PTR_SIZE (BOOTROM_IS_A2() ? 2 : 4)
-#if defined(__riscv)
-#define BOOTROM_ENTRY_OFFSET 0x7dfc
-#define BOOTROM_TABLE_LOOKUP_ENTRY_OFFSET (BOOTROM_ENTRY_OFFSET - BOOTROM_WELL_KNOWN_PTR_SIZE)
-#define BOOTROM_TABLE_LOOKUP_OFFSET (BOOTROM_ENTRY_OFFSET - BOOTROM_WELL_KNOWN_PTR_SIZE*2)
-#else
-#define BOOTROM_VTABLE_OFFSET 0x00
-#define BOOTROM_TABLE_LOOKUP_OFFSET (BOOTROM_FUNC_TABLE_OFFSET + BOOTROM_WELL_KNOWN_PTR_SIZE)
-#endif
-#endif
-
-#if !PICO_RP2040 || PICO_COMBINED_DOCS
-
-#define BOOTROM_OK 0
-//#define BOOTROM_ERROR_TIMEOUT (-1)
-//#define BOOTROM_ERROR_GENERIC (-2)
-//#define BOOTROM_ERROR_NO_DATA (-3) // E.g. read from an empty buffer/FIFO
-#define BOOTROM_ERROR_NOT_PERMITTED (-4) // Permission violation e.g. write to read-only flash partition
-#define BOOTROM_ERROR_INVALID_ARG (-5) // Argument is outside of range of supported values`
-//#define BOOTROM_ERROR_IO (-6)
-//#define BOOTROM_ERROR_BADAUTH (-7)
-//#define BOOTROM_ERROR_CONNECT_FAILED (-8)
-//#define BOOTROM_ERROR_INSUFFICIENT_RESOURCES (-9) // Dynamic allocation of resources failed
-#define BOOTROM_ERROR_INVALID_ADDRESS (-10) // Address argument was out-of-bounds or was determined to be an address that the caller may not access
-#define BOOTROM_ERROR_BAD_ALIGNMENT (-11) // Address modulo transfer chunk size was nonzero (e.g. word-aligned transfer with address % 4 != 0)
-#define BOOTROM_ERROR_INVALID_STATE (-12) // Something happened or failed to happen in the past, and consequently we (currently) can't service the request
-#define BOOTROM_ERROR_BUFFER_TOO_SMALL (-13) // A user-allocated buffer was too small to hold the result or working state of this function
-#define BOOTROM_ERROR_PRECONDITION_NOT_MET (-14) // This call failed because another ROM function must be called first
-#define BOOTROM_ERROR_MODIFIED_DATA (-15) // Cached data was determined to be inconsistent with the full version of the data it was calculated from
-#define BOOTROM_ERROR_INVALID_DATA (-16) // A data structure failed to validate
-#define BOOTROM_ERROR_NOT_FOUND (-17) // Attempted to access something that does not exist; or, a search failed
-#define BOOTROM_ERROR_UNSUPPORTED_MODIFICATION (-18) // Write is impossible based on previous writes; e.g. attempted to clear an OTP bit
-#define BOOTROM_ERROR_LOCK_REQUIRED (-19) // A required lock is not owned
-#define BOOTROM_ERROR_LAST (-19)
-
-#define RT_FLAG_FUNC_RISCV 0x0001
-#define RT_FLAG_FUNC_RISCV_FAR 0x0003
-#define RT_FLAG_FUNC_ARM_SEC 0x0004
-// reserved for 32-bit pointer: 0x0008
-#define RT_FLAG_FUNC_ARM_NONSEC 0x0010
-// reserved for 32-bit pointer: 0x0020
-#define RT_FLAG_DATA 0x0040
-// reserved for 32-bit pointer: 0x0080
-
-#define PARTITION_TABLE_MAX_PARTITIONS 16
-// note this is deliberately > MAX_PARTITIONs is likely to be, and also -1 as a signed byte
-#define PARTITION_TABLE_NO_PARTITION_INDEX 0xff
-
-// todo these are duplicated in picoboot_constants.h
-// values 0-7 are secure/non-secure
-#define BOOT_TYPE_NORMAL 0
-#define BOOT_TYPE_BOOTSEL 2
-#define BOOT_TYPE_RAM_IMAGE 3
-#define BOOT_TYPE_FLASH_UPDATE 4
-
-// values 8-15 are secure only
-#define BOOT_TYPE_PC_SP 0xd
-
-// ORed in if a bootloader chained into the image
-#define BOOT_TYPE_CHAINED_FLAG 0x80
-
-// call from NS to S
-#ifndef __riscv
-#define BOOTROM_API_CALLBACK_secure_call 0
-#endif
-#define BOOTROM_API_CALLBACK_COUNT 1
-
-#define BOOTROM_LOCK_SHA_256 0
-#define BOOTROM_LOCK_FLASH_OP 1
-#define BOOTROM_LOCK_OTP 2
-#define BOOTROM_LOCK_MAX 2
-
-#define BOOTROM_LOCK_ENABLE 7
-
-#define BOOT_PARTITION_NONE (-1)
-#define BOOT_PARTITION_SLOT0 (-2)
-#define BOOT_PARTITION_SLOT1 (-3)
-#define BOOT_PARTITION_WINDOW (-4)
-
-#define BOOT_DIAGNOSTIC_WINDOW_SEARCHED 0x01
-// note if both BOOT_DIAGNOSTIC_INVALID_BLOCK_LOOP and BOOT_DIAGNOSTIC_VALID_BLOCK_LOOP then the block loop was valid
-// but it has a PARTITION_TABLE which while it passed the initial verification (and hash/sig) had invalid contents
-// (discovered when it was later loaded)
-#define BOOT_DIAGNOSTIC_INVALID_BLOCK_LOOP 0x02
-#define BOOT_DIAGNOSTIC_VALID_BLOCK_LOOP 0x04
-#define BOOT_DIAGNOSTIC_VALID_IMAGE_DEF 0x08
-#define BOOT_DIAGNOSTIC_HAS_PARTITION_TABLE 0x10
-#define BOOT_DIAGNOSTIC_CONSIDERED 0x20
-#define BOOT_DIAGNOSTIC_CHOSEN 0x40
-#define BOOT_DIAGNOSTIC_PARTITION_TABLE_LSB 7
-#define BOOT_DIAGNOSTIC_PARTITION_TABLE_MATCHING_KEY_FOR_VERIFY 0x80
-#define BOOT_DIAGNOSTIC_PARTITION_TABLE_HASH_FOR_VERIFY 0x100
-#define BOOT_DIAGNOSTIC_PARTITION_TABLE_VERIFIED_OK 0x200
-#define BOOT_DIAGNOSTIC_IMAGE_DEF_LSB 10
-#define BOOT_DIAGNOSTIC_IMAGE_DEF_MATCHING_KEY_FOR_VERIFY 0x400
-#define BOOT_DIAGNOSTIC_IMAGE_DEF_HASH_FOR_VERIFY 0x800
-#define BOOT_DIAGNOSTIC_IMAGE_DEF_VERIFIED_OK 0x1000
-
-#define BOOT_DIAGNOSTIC_LOAD_MAP_ENTRIES_LOADED 0x2000
-#define BOOT_DIAGNOSTIC_IMAGE_LAUNCHED 0x4000
-#define BOOT_DIAGNOSTIC_IMAGE_CONDITION_FAILURE 0x8000
-
-#define BOOT_PARSED_BLOCK_DIAGNOSTIC_MATCHING_KEY_FOR_VERIFY 0x1 // if this is present and VERIFIED_OK isn't the sig check failed
-#define BOOT_PARSED_BLOCK_DIAGNOSTIC_HASH_FOR_VERIFY 0x2 // if this is present and VERIFIED_OL isn't then hash check failed
-#define BOOT_PARSED_BLOCK_DIAGNOSTIC_VERIFIED_OK 0x4
-
-#define BOOT_TBYB_AND_UPDATE_FLAG_BUY_PENDING 0x1
-#define BOOT_TBYB_AND_UPDATE_FLAG_OTP_VERSION_APPLIED 0x2
-#define BOOT_TBYB_AND_UPDATE_FLAG_OTHER_ERASED 0x4
-
-#ifndef __ASSEMBLER__
-// Limited to 3 arguments in case of varm multiplex hint (trashes Arm r3)
-typedef int (*bootrom_api_callback_generic_t)(uint32_t r0, uint32_t r1, uint32_t r2);
-// Return negative for error, else number of bytes transferred:
-//typedef int (*bootrom_api_callback_stdout_put_blocking_t)(const uint8_t *buffer, uint32_t size);
-//typedef int (*bootrom_api_callback_stdin_get_t)(uint8_t *buffer, uint32_t size);
-//typedef void (*bootrom_api_callback_core1_security_setup_t)(void);
-#endif
-
-#endif
-
-/*! \brief Return a bootrom lookup code based on two ASCII characters
- * \ingroup pico_bootrom
- *
- * These codes are uses to lookup data or function addresses in the bootrom
- *
- * \param c1 the first character
- * \param c2 the second character
- * \return the 'code' to use in rom_func_lookup() or rom_data_lookup()
- */
-#define ROM_TABLE_CODE(c1, c2) ((c1) | ((c2) << 8))
-
-// ROM FUNCTIONS
-
-// RP2040 & RP2350
-#define ROM_DATA_SOFTWARE_GIT_REVISION ROM_TABLE_CODE('G', 'R')
-#define ROM_FUNC_FLASH_ENTER_CMD_XIP ROM_TABLE_CODE('C', 'X')
-#define ROM_FUNC_FLASH_EXIT_XIP ROM_TABLE_CODE('E', 'X')
-#define ROM_FUNC_FLASH_FLUSH_CACHE ROM_TABLE_CODE('F', 'C')
-#define ROM_FUNC_CONNECT_INTERNAL_FLASH ROM_TABLE_CODE('I', 'F')
-#define ROM_FUNC_FLASH_RANGE_ERASE ROM_TABLE_CODE('R', 'E')
-#define ROM_FUNC_FLASH_RANGE_PROGRAM ROM_TABLE_CODE('R', 'P')
-
-
-#if PICO_RP2040
-// RP2040 only
-#define ROM_FUNC_MEMCPY44 ROM_TABLE_CODE('C', '4')
-#define ROM_DATA_COPYRIGHT ROM_TABLE_CODE('C', 'R')
-#define ROM_FUNC_CLZ32 ROM_TABLE_CODE('L', '3')
-#define ROM_FUNC_MEMCPY ROM_TABLE_CODE('M', 'C')
-#define ROM_FUNC_MEMSET ROM_TABLE_CODE('M', 'S')
-#define ROM_FUNC_POPCOUNT32 ROM_TABLE_CODE('P', '3')
-#define ROM_FUNC_REVERSE32 ROM_TABLE_CODE('R', '3')
-#define ROM_FUNC_MEMSET4 ROM_TABLE_CODE('S', '4')
-#define ROM_FUNC_CTZ32 ROM_TABLE_CODE('T', '3')
-#define ROM_FUNC_RESET_USB_BOOT ROM_TABLE_CODE('U', 'B')
-#endif
-
-#if !PICO_RP2040 || PICO_COMBINED_DOCS
-// RP2350 only
-#define ROM_FUNC_PICK_AB_PARTITION ROM_TABLE_CODE('A', 'B')
-#define ROM_FUNC_CHAIN_IMAGE ROM_TABLE_CODE('C', 'I')
-#define ROM_FUNC_EXPLICIT_BUY ROM_TABLE_CODE('E', 'B')
-#define ROM_FUNC_FLASH_RUNTIME_TO_STORAGE_ADDR ROM_TABLE_CODE('F', 'A')
-#define ROM_DATA_FLASH_DEVINFO16_PTR ROM_TABLE_CODE('F', 'D')
-#define ROM_FUNC_FLASH_OP ROM_TABLE_CODE('F', 'O')
-#define ROM_FUNC_GET_B_PARTITION ROM_TABLE_CODE('G', 'B')
-#define ROM_FUNC_GET_PARTITION_TABLE_INFO ROM_TABLE_CODE('G', 'P')
-#define ROM_FUNC_GET_SYS_INFO ROM_TABLE_CODE('G', 'S')
-#define ROM_FUNC_GET_UF2_TARGET_PARTITION ROM_TABLE_CODE('G', 'U')
-#define ROM_FUNC_LOAD_PARTITION_TABLE ROM_TABLE_CODE('L', 'P')
-#define ROM_FUNC_OTP_ACCESS ROM_TABLE_CODE('O', 'A')
-#define ROM_DATA_PARTITION_TABLE_PTR ROM_TABLE_CODE('P', 'T')
-#define ROM_FUNC_FLASH_RESET_ADDRESS_TRANS ROM_TABLE_CODE('R', 'A')
-#define ROM_FUNC_REBOOT ROM_TABLE_CODE('R', 'B')
-#define ROM_FUNC_SET_ROM_CALLBACK ROM_TABLE_CODE('R', 'C')
-#define ROM_FUNC_SECURE_CALL ROM_TABLE_CODE('S', 'C')
-#define ROM_FUNC_SET_NS_API_PERMISSION ROM_TABLE_CODE('S', 'P')
-#define ROM_FUNC_BOOTROM_STATE_RESET ROM_TABLE_CODE('S', 'R')
-#define ROM_FUNC_SET_BOOTROM_STACK ROM_TABLE_CODE('S', 'S')
-#define ROM_DATA_SAVED_XIP_SETUP_FUNC_PTR ROM_TABLE_CODE('X', 'F')
-#define ROM_FUNC_FLASH_SELECT_XIP_READ_MODE ROM_TABLE_CODE('X', 'M')
-#define ROM_FUNC_VALIDATE_NS_BUFFER ROM_TABLE_CODE('V', 'B')
-#endif
-
-// these form a bit set
-#define BOOTROM_STATE_RESET_CURRENT_CORE 0x01
-#define BOOTROM_STATE_RESET_OTHER_CORE 0x02
-#define BOOTROM_STATE_RESET_GLOBAL_STATE 0x04 // reset any global state (e.g. permissions)
-
-// partition level stuff is returned first (note PT_INFO flags is only 16 bits)
-
-// 3 words: pt_count, unpartitioned_perm_loc, unpartioned_perm_flags
-#define PT_INFO_PT_INFO 0x0001
-#define PT_INFO_SINGLE_PARTITION 0x8000 // marker to just include a single partition in the results)
-
-// then in order per partition selected
-
-// 2 words: unpartitioned_perm_loc, unpartioned_perm_flags
-#define PT_INFO_PARTITION_LOCATION_AND_FLAGS 0x0010
-// 2 words: id lsb first
-#define PT_INFO_PARTITION_ID 0x0020
-// n+1 words: n, family_id...
-#define PT_INFO_PARTITION_FAMILY_IDS 0x0040
-// (n+3)/4 words... bytes are: n (len), c0, c1, ... cn-1 padded to word boundary with zeroes
-#define PT_INFO_PARTITION_NAME 0x0080
-
-// items are returned in order
-// 3 words package_id, device_id, wafer_id
-#define SYS_INFO_CHIP_INFO 0x0001
-// 1 word: chip specific critical bits
-#define SYS_INFO_CRITICAL 0x0002
-// 1 word: bytes: cpu_type, supported_cpu_type_bitfield
-#define SYS_INFO_CPU_INFO 0x0004
-// 1 word: same as FLASH_DEVINFO row in OTP
-#define SYS_INFO_FLASH_DEV_INFO 0x0008
-// 4 words
-#define SYS_INFO_BOOT_RANDOM 0x0010
-// 2 words lsb first
-#define SYS_INFO_NONCE 0x0020
-// 4 words boot_info, boot_diagnostic, boot_param0, boot_param1
-#define SYS_INFO_BOOT_INFO 0x0040
-
-#define BOOTROM_NS_API_get_sys_info 0
-#define BOOTROM_NS_API_checked_flash_op 1
-#define BOOTROM_NS_API_flash_runtime_to_storage_addr 2
-#define BOOTROM_NS_API_get_partition_table_info 3
-#define BOOTROM_NS_API_secure_call 4
-#define BOOTROM_NS_API_otp_access 5
-#define BOOTROM_NS_API_reboot 6
-#define BOOTROM_NS_API_get_b_partition 7
-#define BOOTROM_NS_API_COUNT 8
-
-#ifndef __ASSEMBLER__
-
-typedef struct {
- uint32_t permissions_and_location;
- uint32_t permissions_and_flags;
-} resident_partition_t;
-static_assert(sizeof(resident_partition_t) == 8, "");
-
-#define OTP_CMD_ROW_BITS 0x0000ffffu
-#define OTP_CMD_ROW_LSB 0u
-#define OTP_CMD_WRITE_BITS 0x00010000u
-#define OTP_CMD_ECC_BITS 0x00020000u
-
-typedef struct otp_cmd {
- uint32_t flags;
-} otp_cmd_t;
-
-typedef enum {
- BOOTROM_XIP_MODE_03H_SERIAL = 0,
- BOOTROM_XIP_MODE_0BH_SERIAL,
- BOOTROM_XIP_MODE_BBH_DUAL,
- BOOTROM_XIP_MODE_EBH_QUAD,
- BOOTROM_XIP_MODE_N_MODES
-} bootrom_xip_mode_t;
-
-// The checked flash API wraps the low-level flash routines from generic_flash, adding bounds
-// checking, permission checking against the resident partition table, and simple address
-// translation. The low-level API deals with flash offsets (i.e. distance from the start of the
-// first flash device, measured in bytes) but the checked flash API accepts one of two types of
-// address:
-//
-// - Flash runtime addresses: the address of some flash-resident data or code in the currently
-// running image. The flash addresses your binary is "linked at" by the linker.
-// - Flash storage addresses: a flash offset, plus the address base where QSPI hardware is first
-// mapped on the system bus (XIP_BASE constant from addressmap.h)
-//
-// These addresses are one and the same *if* the currently running program is stored at the
-// beginning of flash. They are different if the start of your image has been "rolled" by the flash
-// boot path to make it appear at the address it was linked at even though it is stored at a
-// different location in flash, which is necessary when you have A/B images for example.
-//
-// The address translation between flash runtime and flash storage addresses is configured in
-// hardware by the QMI_ATRANSx registers, and this API assumes those registers contain a valid
-// address mapping which it can use to translate runtime to storage addresses.
-
-typedef struct cflash_flags {
- uint32_t flags;
-} cflash_flags_t;
-
-// Bits which are permitted to be set in a flags variable -- any other bits being set is an error
-#define CFLASH_FLAGS_BITS 0x00070301u
-
-// Used to tell checked flash API which space a given address belongs to
-#define CFLASH_ASPACE_BITS 0x00000001u
-#define CFLASH_ASPACE_LSB 0u
-#define CFLASH_ASPACE_VALUE_STORAGE 0u
-#define CFLASH_ASPACE_VALUE_RUNTIME 1u
-
-// Used to tell checked flash APIs the effective security level of a flash access (may be forced to
-// one of these values for the NonSecure-exported version of this API)
-#define CFLASH_SECLEVEL_BITS 0x00000300u
-#define CFLASH_SECLEVEL_LSB 8u
-// Zero is not a valid security level:
-#define CFLASH_SECLEVEL_VALUE_SECURE 1u
-#define CFLASH_SECLEVEL_VALUE_NONSECURE 2u
-#define CFLASH_SECLEVEL_VALUE_BOOTLOADER 3u
-
-#define CFLASH_OP_BITS 0x00070000u
-#define CFLASH_OP_LSB 16u
-// Erase size_bytes bytes of flash, starting at address addr. Both addr and size_bytes must be a
-// multiple of 4096 bytes (one flash sector).
-#define CFLASH_OP_VALUE_ERASE 0u
-// Program size_bytes bytes of flash, starting at address addr. Both addr and size_bytes must be a
-// multiple of 256 bytes (one flash page).
-#define CFLASH_OP_VALUE_PROGRAM 1u
-// Read size_bytes bytes of flash, starting at address addr. There are no alignment restrictions on
-// addr or size_bytes.
-#define CFLASH_OP_VALUE_READ 2u
-#define CFLASH_OP_MAX 2u
-
-#endif
-
-#endif
+// new location; this file kept for backwards compatibility
+#include "boot/bootrom_constants.h"
diff --git a/src/rp2_common/pico_bootsel_via_double_reset/pico_bootsel_via_double_reset.c b/src/rp2_common/pico_bootsel_via_double_reset/pico_bootsel_via_double_reset.c
index ae86c5bed..8028936e2 100644
--- a/src/rp2_common/pico_bootsel_via_double_reset/pico_bootsel_via_double_reset.c
+++ b/src/rp2_common/pico_bootsel_via_double_reset/pico_bootsel_via_double_reset.c
@@ -13,12 +13,21 @@
#include "pico/bootrom.h"
#include "pico/binary_info.h"
+#if !PICO_RP2040
+#include "hardware/structs/powman.h"
+#endif
+
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS, Window of opportunity for a second press of a reset button to enter BOOTSEL mode (milliseconds), type=int, default=200, group=pico_bootsel_via_double_reset
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS 200
#endif
-// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via reset double tap, type=int, min=0, max=29, group=pico_bootsel_via_double_reset
+// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via reset double tap, type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_bootsel_via_double_reset
+
+// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW, Whether pin used as bootloader activity LED when BOOTSEL mode is entered via reset double tap is active low. Not supported on RP2040, type=bool, default=0, group=pico_bootsel_via_double_reset
+#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW
+#define PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW 0
+#endif
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via double reset, type=int, min=0, max=3, default=0, group=pico_bootsel_via_double_reset
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
@@ -41,12 +50,62 @@
bi_decl(bi_program_feature("double reset -> BOOTSEL"));
#endif
+#if PICO_RP2040
+
+// RP2040 stores a token in RAM, which is retained over assertion of the RUN pin.
+
static const uint32_t magic_token[] = {
0xf01681de, 0xbd729b29, 0xd359be7a,
};
static uint32_t __uninitialized_ram(magic_location)[count_of(magic_token)];
+static inline bool double_tap_flag_is_set(void) {
+ for (uint i = 0; i < count_of(magic_token); i++) {
+ if (magic_location[i] != magic_token[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline void set_double_tap_flag(void) {
+ for (uint i = 0; i < count_of(magic_token); i++) {
+ magic_location[i] = magic_token[i];
+ }
+}
+
+static inline void clear_double_tap_flag(void) {
+ magic_location[0] = 0;
+}
+
+#else
+
+// Newer microcontrollers have a purpose-made register which is retained over
+// RUN events, for detecting double-tap events. The ROM has built-in support
+// for this, but this library can also use the same hardware feature.
+// (Also, RAM is powered down when the RUN pin is asserted, so it's a bad
+// place to put the token!)
+//
+// Note if ROM support is also enabled (via DOUBLE_TAP in OTP BOOT_FLAGS) then
+// we never reach this point with the double tap flag still set. The window
+// is the sum of the delay added by this library and the delay added by the
+// ROM. It's not recommended to enable both, but it works.
+
+static inline bool double_tap_flag_is_set(void) {
+ return powman_hw->chip_reset & POWMAN_CHIP_RESET_DOUBLE_TAP_BITS;
+}
+
+static inline void set_double_tap_flag(void) {
+ hw_set_bits(&powman_hw->chip_reset, POWMAN_CHIP_RESET_DOUBLE_TAP_BITS);
+}
+
+static inline void clear_double_tap_flag(void) {
+ hw_clear_bits(&powman_hw->chip_reset, POWMAN_CHIP_RESET_DOUBLE_TAP_BITS);
+}
+
+#endif
+
/* Check for double reset and enter BOOTSEL mode if detected
*
* This function is registered to run automatically before main(). The
@@ -62,27 +121,25 @@ static uint32_t __uninitialized_ram(magic_location)[count_of(magic_token)];
* in place so that the second boot will go to the bootloader.
*/
static void __attribute__((constructor)) boot_double_tap_check(void) {
- for (uint i = 0; i < count_of(magic_token); i++) {
- if (magic_location[i] != magic_token[i]) {
- // Arm, wait, then disarm and continue booting
- for (i = 0; i < count_of(magic_token); i++) {
- magic_location[i] = magic_token[i];
- }
- busy_wait_us(PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS * 1000);
- magic_location[0] = 0;
- return;
- }
+ if (!double_tap_flag_is_set()) {
+ // Arm, wait, then disarm and continue booting
+ set_double_tap_flag();
+ busy_wait_us(PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS * 1000);
+ clear_double_tap_flag();
+ return;
}
+
// Detected a double reset, so enter USB bootloader
- magic_location[0] = 0;
+ clear_double_tap_flag();
#ifdef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED
- const uint32_t led_mask = 1u << PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED;
+ const int led = PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED;
#else
- const uint32_t led_mask = 0u;
+ const int led = -1;
#endif
- reset_usb_boot(
- led_mask,
- PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
+ rom_reset_usb_boot_extra(
+ led,
+ PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK,
+ PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED_ACTIVE_LOW
);
}
diff --git a/src/rp2_common/pico_btstack/BUILD.bazel b/src/rp2_common/pico_btstack/BUILD.bazel
index 0f843b47f..5d88ad690 100644
--- a/src/rp2_common/pico_btstack/BUILD.bazel
+++ b/src/rp2_common/pico_btstack/BUILD.bazel
@@ -2,6 +2,28 @@ load("//bazel:defs.bzl", "compatible_with_pico_w", "incompatible_with_config")
package(default_visibility = ["//visibility:public"])
+# Prefer using this target to link in all the enabled bt modules, as it will
+# link the appropriate libraries and set the appropraite defines based on the
+# following flags:
+#
+# --@pico-sdk//bazel/constraint:PICO_BT_ENABLE_BLE
+# --@pico-sdk//bazel/constraint:PICO_BT_ENABLE_CLASSIC
+# --@pico-sdk//bazel/constraint:PICO_BT_ENABLE_MESH
+cc_library(
+ name = "pico_btstack",
+ deps = ["pico_btstack_base"] + select({
+ "//bazel/constraint:pico_bt_enable_ble_enabled": [":pico_btstack_ble"],
+ "//conditions:default": [],
+ }) + select({
+ "//bazel/constraint:pico_bt_enable_classic_enabled": [":pico_btstack_classic"],
+ "//conditions:default": [],
+ }) + select({
+ "//bazel/constraint:pico_bt_enable_mesh_enabled": [":pico_btstack_mesh"],
+ "//conditions:default": [],
+ }),
+ target_compatible_with = incompatible_with_config("//bazel/constraint:pico_btstack_config_unset"),
+)
+
# Prefer these aliases to directly referencing @btstack, as it's possible that
# name may change.
alias(
@@ -19,9 +41,19 @@ alias(
actual = "@btstack//:pico_btstack_classic",
)
+alias(
+ name = "pico_btstack_mesh",
+ actual = "@btstack//:pico_btstack_mesh",
+)
+
alias(
name = "pico_btstack_sbc_encoder",
- actual = "@btstack//:pico_btstack_classic",
+ actual = "@btstack//:pico_btstack_sbc_encoder",
+)
+
+alias(
+ name = "pico_btstack_sbc_decoder",
+ actual = "@btstack//:pico_btstack_sbc_decoder",
)
alias(
@@ -63,11 +95,12 @@ cc_library(
cc_library(
name = "pico_btstack_stdin",
srcs = ["btstack_stdin_pico.c"],
- target_compatible_with = incompatible_with_config(
- "//bazel/constraint:pico_btstack_config_unset",
- ) + compatible_with_pico_w(),
+ target_compatible_with = compatible_with_pico_w() + incompatible_with_config("//bazel/constraint:pico_btstack_config_unset"),
deps = [
+ ":pico_btstack_base",
+ "//bazel/config:PICO_BTSTACK_CONFIG",
"//src/rp2_common:pico_platform",
"//src/rp2_common/pico_stdio",
],
+ alwayslink = True,
)
diff --git a/src/rp2_common/pico_btstack/CMakeLists.txt b/src/rp2_common/pico_btstack/CMakeLists.txt
index 6a821442a..c622cacf5 100644
--- a/src/rp2_common/pico_btstack/CMakeLists.txt
+++ b/src/rp2_common/pico_btstack/CMakeLists.txt
@@ -28,7 +28,6 @@ if (EXISTS ${PICO_BTSTACK_PATH}/${BTSTACK_TEST_PATH})
target_sources(pico_btstack_base INTERFACE
${PICO_BTSTACK_PATH}/3rd-party/micro-ecc/uECC.c
${PICO_BTSTACK_PATH}/3rd-party/rijndael/rijndael.c
- ${PICO_BTSTACK_PATH}/3rd-party/segger-rtt/SEGGER_RTT.c
${PICO_BTSTACK_PATH}/3rd-party/segger-rtt/SEGGER_RTT_printf.c
${PICO_BTSTACK_PATH}/platform/embedded/btstack_tlv_flash_bank.c
${PICO_BTSTACK_PATH}/platform/embedded/hci_dump_embedded_stdout.c
@@ -56,12 +55,17 @@ if (EXISTS ${PICO_BTSTACK_PATH}/${BTSTACK_TEST_PATH})
${PICO_BTSTACK_PATH}/src/hci_event.c
${PICO_BTSTACK_PATH}/src/l2cap.c
${PICO_BTSTACK_PATH}/src/l2cap_signaling.c
- ${PICO_BTSTACK_PATH}/src/mesh/gatt-service/mesh_provisioning_service_server.c
- ${PICO_BTSTACK_PATH}/src/mesh/gatt-service/mesh_proxy_service_server.c
${PICO_BTSTACK_PATH}/3rd-party/md5/md5.c
${PICO_BTSTACK_PATH}/3rd-party/yxml/yxml.c
${CMAKE_CURRENT_LIST_DIR}/btstack_stdin_pico.c
)
+ # pico-sdk now supports RTT using pico_enable_stdio_rtt in your cmake file or -DPICO_STDIO_RTT=1 on the command line
+ # Then the output of printf goes to RTT. But if you define ENABLE_SEGGER_RTT=1 it will use the btstack functionality to use RTT
+ # and we'll have to add the source file it requires.
+ target_sources(pico_btstack_base INTERFACE
+ $,>,${PICO_STDIO_RTT},$>>,,${PICO_BTSTACK_PATH}/3rd-party/segger-rtt/SEGGER_RTT.c>
+ )
+
target_include_directories(pico_btstack_base_headers SYSTEM INTERFACE
${PICO_BTSTACK_PATH}/
${PICO_BTSTACK_PATH}/3rd-party/md5
@@ -157,6 +161,48 @@ if (EXISTS ${PICO_BTSTACK_PATH}/${BTSTACK_TEST_PATH})
ENABLE_CLASSIC=1
)
+ pico_add_library(pico_btstack_mesh)
+ target_sources(pico_btstack_mesh INTERFACE
+ ${PICO_BTSTACK_PATH}/src/mesh/adv_bearer.c
+ ${PICO_BTSTACK_PATH}/src/mesh/beacon.c
+ ${PICO_BTSTACK_PATH}/src/mesh/gatt_bearer.c
+ ${PICO_BTSTACK_PATH}/src/mesh/gatt-service/mesh_provisioning_service_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/gatt-service/mesh_proxy_service_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_access.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_configuration_client.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_configuration_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_crypto.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_foundation.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_generic_default_transition_time_client.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_generic_default_transition_time_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_generic_level_client.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_generic_level_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_generic_on_off_client.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_generic_on_off_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_health_server.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_iv_index_seq_number.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_keys.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_lower_transport.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_network.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_node.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_peer.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_proxy.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_upper_transport.c
+ ${PICO_BTSTACK_PATH}/src/mesh/mesh_virtual_addresses.c
+ ${PICO_BTSTACK_PATH}/src/mesh/pb_adv.c
+ ${PICO_BTSTACK_PATH}/src/mesh/pb_gatt.c
+ ${PICO_BTSTACK_PATH}/src/mesh/provisioning.c
+ ${PICO_BTSTACK_PATH}/src/mesh/provisioning_device.c
+ ${PICO_BTSTACK_PATH}/src/mesh/provisioning_provisioner.c
+ )
+ pico_mirrored_target_link_libraries(pico_btstack_mesh INTERFACE
+ pico_btstack_ble
+ )
+ target_compile_definitions(pico_btstack_mesh_headers INTERFACE
+ ENABLE_MESH=1
+ )
+
pico_add_library(pico_btstack_flash_bank)
target_sources(pico_btstack_flash_bank INTERFACE
${CMAKE_CURRENT_LIST_DIR}/btstack_flash_bank.c
diff --git a/src/rp2_common/pico_btstack/btstack.BUILD b/src/rp2_common/pico_btstack/btstack.BUILD
index ac009d9e9..7ec56537a 100644
--- a/src/rp2_common/pico_btstack/btstack.BUILD
+++ b/src/rp2_common/pico_btstack/btstack.BUILD
@@ -1,7 +1,14 @@
-load("@pico-sdk//bazel:defs.bzl", "incompatible_with_config")
+load("@rules_python//python:defs.bzl", "py_binary")
+load("@pico-sdk//bazel:defs.bzl", "compatible_with_config", "incompatible_with_config")
package(default_visibility = ["//visibility:public"])
+# Expose the gatt header for pico_btstack_make_gatt_header.
+exports_files(
+ ["src/bluetooth_gatt.h"],
+ visibility = ["@pico-sdk//bazel:__pkg__"],
+)
+
_DISABLE_WARNINGS = [
"-Wno-cast-qual",
"-Wno-format",
@@ -14,15 +21,44 @@ _DISABLE_WARNINGS = [
"-Wno-unused-parameter",
]
+cc_library(
+ name = "pico_btstack_base_headers",
+ hdrs = glob(["**/*.h"]),
+ visibility = ["//visibility:private"],
+ defines = select({
+ "@pico-sdk//bazel/constraint:pico_bt_enable_ble_enabled": ["ENABLE_BLE=1"],
+ "//conditions:default": [],
+ }) + select({
+ "@pico-sdk//bazel/constraint:pico_bt_enable_mesh_enabled": ["ENABLE_MESH=1"],
+ "//conditions:default": [],
+ }) + select({
+ "@pico-sdk//bazel/constraint:pico_bt_enable_classic_enabled": ["ENABLE_CLASSIC=1"],
+ "//conditions:default": [],
+ }),
+ includes = [
+ ".",
+ "3rd-party/bluedroid/decoder/include",
+ "3rd-party/bluedroid/encoder/include",
+ "3rd-party/md5",
+ "3rd-party/micro-ecc",
+ "3rd-party/rijndael",
+ "3rd-party/segger-rtt",
+ "3rd-party/yxml",
+ "platform/embedded",
+ "src",
+ ],
+ deps = [
+ "@pico-sdk//bazel/config:PICO_BTSTACK_CONFIG"
+ ],
+)
+
cc_library(
name = "pico_btstack_base",
srcs = [
- "3rd-party/md5/md5.c",
"3rd-party/micro-ecc/uECC.c",
"3rd-party/rijndael/rijndael.c",
"3rd-party/segger-rtt/SEGGER_RTT.c",
"3rd-party/segger-rtt/SEGGER_RTT_printf.c",
- "3rd-party/yxml/yxml.c",
"platform/embedded/btstack_tlv_flash_bank.c",
"platform/embedded/hci_dump_embedded_stdout.c",
"platform/embedded/hci_dump_segger_rtt_stdout.c",
@@ -30,6 +66,7 @@ cc_library(
"src/btstack_audio.c",
"src/btstack_base64_decoder.c",
"src/btstack_crypto.c",
+ "src/btstack_hid.c",
"src/btstack_hid_parser.c",
"src/btstack_linked_list.c",
"src/btstack_memory.c",
@@ -48,25 +85,13 @@ cc_library(
"src/hci_event.c",
"src/l2cap.c",
"src/l2cap_signaling.c",
- "src/mesh/gatt-service/mesh_provisioning_service_server.c",
- "src/mesh/gatt-service/mesh_proxy_service_server.c",
+ "3rd-party/md5/md5.c",
+ "3rd-party/yxml/yxml.c",
],
- hdrs = glob(["**/*.h"]),
copts = _DISABLE_WARNINGS,
- includes = [
- ".",
- "3rd-party/md5",
- "3rd-party/micro-ecc",
- "3rd-party/rijndael",
- "3rd-party/segger-rtt",
- "3rd-party/yxml",
- "platform/embedded",
- "src",
- ],
- target_compatible_with = incompatible_with_config(
- "@pico-sdk//bazel/constraint:pico_btstack_config_unset",
- ),
- deps = ["@pico-sdk//bazel/config:PICO_BTSTACK_CONFIG"],
+ target_compatible_with = incompatible_with_config("@pico-sdk//bazel/constraint:pico_btstack_config_unset"),
+ deps = [":pico_btstack_base_headers"],
+ alwayslink = True,
)
cc_library(
@@ -76,25 +101,27 @@ cc_library(
"src/ble/att_db_util.c",
"src/ble/att_dispatch.c",
"src/ble/att_server.c",
- "src/ble/gatt-service/ancs_client.c",
- "src/ble/gatt-service/battery_service_client.c",
"src/ble/gatt-service/battery_service_server.c",
+ "src/ble/gatt-service/battery_service_client.c",
"src/ble/gatt-service/cycling_power_service_server.c",
"src/ble/gatt-service/cycling_speed_and_cadence_service_server.c",
- "src/ble/gatt-service/device_information_service_client.c",
"src/ble/gatt-service/device_information_service_server.c",
+ "src/ble/gatt-service/device_information_service_client.c",
"src/ble/gatt-service/heart_rate_service_server.c",
"src/ble/gatt-service/hids_client.c",
"src/ble/gatt-service/hids_device.c",
"src/ble/gatt-service/nordic_spp_service_server.c",
"src/ble/gatt-service/ublox_spp_service_server.c",
+ "src/ble/gatt-service/ancs_client.c",
"src/ble/gatt_client.c",
"src/ble/le_device_db_memory.c",
"src/ble/le_device_db_tlv.c",
"src/ble/sm.c",
],
copts = _DISABLE_WARNINGS,
- deps = [":pico_btstack_base"],
+ target_compatible_with = compatible_with_config("@pico-sdk//bazel/constraint:pico_bt_enable_ble_enabled"),
+ deps = [":pico_btstack_base_headers"],
+ alwayslink = True,
)
cc_library(
@@ -146,12 +173,70 @@ cc_library(
"src/classic/spp_server.c",
],
copts = _DISABLE_WARNINGS,
- deps = [":pico_btstack_base"],
+ target_compatible_with = compatible_with_config("@pico-sdk//bazel/constraint:pico_bt_enable_classic_enabled"),
+ deps = [
+ ":pico_btstack_base",
+ ":pico_btstack_base_headers",
+ ],
+ alwayslink = True,
+)
+
+cc_library(
+ name = "pico_btstack_mesh",
+ srcs = [
+ "src/mesh/adv_bearer.c",
+ "src/mesh/beacon.c",
+ "src/mesh/gatt_bearer.c",
+ "src/mesh/gatt-service/mesh_provisioning_service_server.c",
+ "src/mesh/gatt-service/mesh_proxy_service_server.c",
+ "src/mesh/mesh.c",
+ "src/mesh/mesh_access.c",
+ "src/mesh/mesh_configuration_client.c",
+ "src/mesh/mesh_configuration_server.c",
+ "src/mesh/mesh_crypto.c",
+ "src/mesh/mesh_foundation.c",
+ "src/mesh/mesh_generic_default_transition_time_client.c",
+ "src/mesh/mesh_generic_default_transition_time_server.c",
+ "src/mesh/mesh_generic_level_client.c",
+ "src/mesh/mesh_generic_level_server.c",
+ "src/mesh/mesh_generic_on_off_client.c",
+ "src/mesh/mesh_generic_on_off_server.c",
+ "src/mesh/mesh_health_server.c",
+ "src/mesh/mesh_iv_index_seq_number.c",
+ "src/mesh/mesh_keys.c",
+ "src/mesh/mesh_lower_transport.c",
+ "src/mesh/mesh_network.c",
+ "src/mesh/mesh_node.c",
+ "src/mesh/mesh_peer.c",
+ "src/mesh/mesh_proxy.c",
+ "src/mesh/mesh_upper_transport.c",
+ "src/mesh/mesh_virtual_addresses.c",
+ "src/mesh/pb_adv.c",
+ "src/mesh/pb_gatt.c",
+ "src/mesh/provisioning.c",
+ "src/mesh/provisioning_device.c",
+ "src/mesh/provisioning_provisioner.c",
+ ],
+ copts = _DISABLE_WARNINGS,
+ target_compatible_with = compatible_with_config("@pico-sdk//bazel/constraint:pico_bt_enable_mesh_enabled"),
+ deps = [
+ ":pico_btstack_base_headers",
+ ":pico_btstack_ble",
+ ],
+ alwayslink = True,
+)
+
+cc_library(
+ name = "pico_btstack_sbc_common",
+ srcs = ["src/classic/btstack_sbc_bluedroid.c"],
+ deps = [":pico_btstack_base_headers"],
+ target_compatible_with = incompatible_with_config("@pico-sdk//bazel/constraint:pico_btstack_config_unset"),
)
cc_library(
name = "pico_btstack_sbc_encoder",
srcs = [
+ "src/classic/btstack_sbc_encoder_bluedroid.c",
"3rd-party/bluedroid/encoder/srce/sbc_analysis.c",
"3rd-party/bluedroid/encoder/srce/sbc_dct.c",
"3rd-party/bluedroid/encoder/srce/sbc_dct_coeffs.c",
@@ -160,11 +245,43 @@ cc_library(
"3rd-party/bluedroid/encoder/srce/sbc_enc_coeffs.c",
"3rd-party/bluedroid/encoder/srce/sbc_encoder.c",
"3rd-party/bluedroid/encoder/srce/sbc_packing.c",
- "src/classic/btstack_sbc_encoder_bluedroid.c",
],
copts = _DISABLE_WARNINGS,
includes = ["3rd-party/bluedroid/decoder/include"],
- deps = [":pico_btstack_base"],
+ deps = [
+ ":pico_btstack_base_headers",
+ ":pico_btstack_sbc_common",
+ ],
+ alwayslink = True,
+)
+
+cc_library(
+ name = "pico_btstack_sbc_decoder",
+ srcs = [
+ "src/classic/btstack_sbc_decoder_bluedroid.c",
+ "3rd-party/bluedroid/decoder/srce/readsamplesjoint.inc",
+ "3rd-party/bluedroid/decoder/srce/alloc.c",
+ "3rd-party/bluedroid/decoder/srce/bitalloc.c",
+ "3rd-party/bluedroid/decoder/srce/bitalloc-sbc.c",
+ "3rd-party/bluedroid/decoder/srce/bitstream-decode.c",
+ "3rd-party/bluedroid/decoder/srce/decoder-oina.c",
+ "3rd-party/bluedroid/decoder/srce/decoder-private.c",
+ "3rd-party/bluedroid/decoder/srce/decoder-sbc.c",
+ "3rd-party/bluedroid/decoder/srce/dequant.c",
+ "3rd-party/bluedroid/decoder/srce/framing.c",
+ "3rd-party/bluedroid/decoder/srce/framing-sbc.c",
+ "3rd-party/bluedroid/decoder/srce/oi_codec_version.c",
+ "3rd-party/bluedroid/decoder/srce/synthesis-sbc.c",
+ "3rd-party/bluedroid/decoder/srce/synthesis-dct8.c",
+ "3rd-party/bluedroid/decoder/srce/synthesis-8-generated.c",
+ ],
+ copts = _DISABLE_WARNINGS,
+ includes = ["3rd-party/bluedroid/decoder/include"],
+ deps = [
+ ":pico_btstack_base_headers",
+ ":pico_btstack_sbc_common",
+ ],
+ alwayslink = True,
)
cc_library(
@@ -175,7 +292,10 @@ cc_library(
],
copts = _DISABLE_WARNINGS,
includes = ["platform/lwip"],
- deps = [":pico_btstack_base"],
+ deps = [
+ ":pico_btstack_base_headers",
+ "@pico-sdk//src/rp2_common/pico_lwip:pico_lwip_nosys",
+ ],
)
cc_library(
@@ -193,5 +313,17 @@ cc_library(
"platform/freertos",
"platform/lwip",
],
- deps = [":pico_btstack_base"],
+ deps = [
+ ":pico_btstack_base_headers",
+ "@pico-sdk//src/rp2_common/pico_lwip:pico_lwip_freertos",
+ ],
+)
+
+py_binary(
+ name = "compile_gatt",
+ srcs = [
+ "tool/compile_gatt.py",
+ ],
+ # TODO: Add pip pins.
+ # deps = ["@python_packages//pycryptodomex"]
)
diff --git a/src/rp2_common/pico_btstack/doc.h b/src/rp2_common/pico_btstack/doc.h
index 0adf21901..08bc35b9a 100644
--- a/src/rp2_common/pico_btstack/doc.h
+++ b/src/rp2_common/pico_btstack/doc.h
@@ -20,6 +20,7 @@
* * \c \b pico_btstack_sbc_decoder - Adds Bluetooth Sub Band Coding (SBC) decoder support.
* * \c \b pico_btstack_bnep_lwip - Adds Bluetooth Network Encapsulation Protocol (BNEP) support using LwIP.
* * \c \b pico_btstack_bnep_lwip_sys_freertos - Adds Bluetooth Network Encapsulation Protocol (BNEP) support using LwIP with FreeRTOS for NO_SYS=0.
+ * * \c \b pico_btstack_mesh - Adds Bluetooth mesh support from BTstack.
*
* \note The CMake function pico_btstack_make_gatt_header can be used to run the BTstack compile_gatt tool to make a GATT header file from a BTstack GATT file.
*
diff --git a/src/rp2_common/pico_clib_interface/include/llvm_libc/time.h b/src/rp2_common/pico_clib_interface/include/llvm_libc/time.h
index 2115718a1..bb37c7eff 100644
--- a/src/rp2_common/pico_clib_interface/include/llvm_libc/time.h
+++ b/src/rp2_common/pico_clib_interface/include/llvm_libc/time.h
@@ -14,7 +14,6 @@
__BEGIN_C_DECLS
-time_t mktime(struct tm* arg);
struct tm* localtime_r(const time_t* timer, struct tm* buf);
__END_C_DECLS
diff --git a/src/rp2_common/pico_clib_interface/picolibc_interface.c b/src/rp2_common/pico_clib_interface/picolibc_interface.c
index b10bb418d..8f7770ab8 100644
--- a/src/rp2_common/pico_clib_interface/picolibc_interface.c
+++ b/src/rp2_common/pico_clib_interface/picolibc_interface.c
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include "pico.h"
#if LIB_PICO_STDIO
@@ -39,6 +40,7 @@ static int picolibc_getc(__unused FILE *file) {
#if LIB_PICO_STDIO
return stdio_getchar();
#endif
+ return -1;
}
static int picolibc_flush(__unused FILE *file) {
@@ -93,6 +95,17 @@ __weak int settimeofday(__unused const struct timeval *tv, __unused const struct
return 0;
}
+__weak clock_t times(struct tms *tms) {
+#if CLOCKS_PER_SEC >= 1000000
+ tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) * (CLOCKS_PER_SEC / 1000000));
+#else
+ tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) / (1000000 / CLOCKS_PER_SEC));
+#endif
+ tms->tms_stime = 0;
+ tms->tms_cutime = 0;
+ tms->tms_cstime = 0;
+ return 0;
+}
void runtime_init(void) {
#ifndef NDEBUG
@@ -118,9 +131,9 @@ __weak void runtime_init_pre_core_tls_setup(void) {
// for now we just set the same global area on both cores
// note: that this is superfluous with the stock picolibc it seems, since it is itself
// using a version of __aeabi_read_tp that returns the same pointer on both cores
- extern void __tls_base;
+ extern char __tls_base[];
extern void _set_tls(void *tls);
- _set_tls(&__tls_base);
+ _set_tls(__tls_base);
}
#endif
diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S
index 9bf12631a..e408b7ded 100644
--- a/src/rp2_common/pico_crt0/crt0.S
+++ b/src/rp2_common/pico_crt0/crt0.S
@@ -52,17 +52,99 @@ __vectors:
// we don't include any IRQ vectors; we will initialize them during runtime_init in the RAM vector table
#else
-.altmacro
-.macro isr_irqx irq_num
-.word isr_irq\irq_num
+.macro if_irq_word num func
+.if \num < NUM_IRQS
+.word \func
+.endif
.endm
-.set irq_num, 0
-.rept NUM_IRQS
-isr_irqx %irq_num
-.set irq_num, irq_num + 1
-.endr
-
+// we include a lot of these to allow for different number of IRQs.
+// if_irq_word will only include IRQs that are valid, but we can't
+// use a macro loop because isr_irqx MUST appear in the source
+// as CMSIS rename exceptions #defines it to another value
+if_irq_word 0 isr_irq0
+if_irq_word 1 isr_irq1
+if_irq_word 2 isr_irq2
+if_irq_word 3 isr_irq3
+if_irq_word 4 isr_irq4
+if_irq_word 5 isr_irq5
+if_irq_word 6 isr_irq6
+if_irq_word 7 isr_irq7
+if_irq_word 8 isr_irq8
+if_irq_word 9 isr_irq9
+if_irq_word 10 isr_irq10
+if_irq_word 11 isr_irq11
+if_irq_word 12 isr_irq12
+if_irq_word 13 isr_irq13
+if_irq_word 14 isr_irq14
+if_irq_word 15 isr_irq15
+if_irq_word 16 isr_irq16
+if_irq_word 17 isr_irq17
+if_irq_word 18 isr_irq18
+if_irq_word 19 isr_irq19
+if_irq_word 20 isr_irq20
+if_irq_word 21 isr_irq21
+if_irq_word 22 isr_irq22
+if_irq_word 23 isr_irq23
+if_irq_word 24 isr_irq24
+if_irq_word 25 isr_irq25
+if_irq_word 26 isr_irq26
+if_irq_word 27 isr_irq27
+if_irq_word 28 isr_irq28
+if_irq_word 29 isr_irq29
+if_irq_word 30 isr_irq30
+if_irq_word 31 isr_irq31
+if_irq_word 32 isr_irq32
+if_irq_word 33 isr_irq33
+if_irq_word 34 isr_irq34
+if_irq_word 35 isr_irq35
+if_irq_word 36 isr_irq36
+if_irq_word 37 isr_irq37
+if_irq_word 38 isr_irq38
+if_irq_word 39 isr_irq39
+if_irq_word 40 isr_irq40
+if_irq_word 41 isr_irq41
+if_irq_word 42 isr_irq42
+if_irq_word 43 isr_irq43
+if_irq_word 44 isr_irq44
+if_irq_word 45 isr_irq45
+if_irq_word 46 isr_irq46
+if_irq_word 47 isr_irq47
+if_irq_word 48 isr_irq48
+if_irq_word 49 isr_irq49
+if_irq_word 50 isr_irq50
+if_irq_word 51 isr_irq51
+if_irq_word 52 isr_irq52
+if_irq_word 53 isr_irq53
+if_irq_word 54 isr_irq54
+if_irq_word 55 isr_irq55
+if_irq_word 56 isr_irq56
+if_irq_word 57 isr_irq57
+if_irq_word 58 isr_irq58
+if_irq_word 59 isr_irq59
+if_irq_word 60 isr_irq60
+if_irq_word 61 isr_irq61
+if_irq_word 62 isr_irq62
+if_irq_word 63 isr_irq63
+if_irq_word 64 isr_irq64
+if_irq_word 65 isr_irq65
+if_irq_word 66 isr_irq66
+if_irq_word 67 isr_irq67
+if_irq_word 68 isr_irq68
+if_irq_word 69 isr_irq69
+if_irq_word 70 isr_irq70
+if_irq_word 71 isr_irq71
+if_irq_word 72 isr_irq72
+if_irq_word 73 isr_irq73
+if_irq_word 74 isr_irq74
+if_irq_word 75 isr_irq75
+if_irq_word 76 isr_irq76
+if_irq_word 77 isr_irq77
+if_irq_word 78 isr_irq78
+if_irq_word 79 isr_irq79
+#if NUM_IRQS > 80
+#error more IRQ entries required
+#endif
#endif
// all default exception handlers do nothing, and we can check for them being set to our
@@ -93,6 +175,7 @@ decl_isr_bkpt isr_systick
.global __default_isrs_end
__default_isrs_end:
+.altmacro
.macro decl_isr name
#if !PICO_NO_STORED_VECTOR_TABLE | PICO_NO_FLASH
// We declare a weak label, so user can override
@@ -105,15 +188,95 @@ __default_isrs_end:
\name:
.endm
-.macro decl_isrx irq_num
-decl_isr isr_irq\irq_num
+.macro if_irq_decl num func
+.if \num < NUM_IRQS
+decl_isr \func
+.endif
.endm
-.set irq_num, 0
-.rept NUM_IRQS
-decl_isrx %irq_num
-.set irq_num, irq_num + 1
-.endr
+if_irq_decl 0 isr_irq0
+if_irq_decl 1 isr_irq1
+if_irq_decl 2 isr_irq2
+if_irq_decl 3 isr_irq3
+if_irq_decl 4 isr_irq4
+if_irq_decl 5 isr_irq5
+if_irq_decl 6 isr_irq6
+if_irq_decl 7 isr_irq7
+if_irq_decl 8 isr_irq8
+if_irq_decl 9 isr_irq9
+if_irq_decl 10 isr_irq10
+if_irq_decl 11 isr_irq11
+if_irq_decl 12 isr_irq12
+if_irq_decl 13 isr_irq13
+if_irq_decl 14 isr_irq14
+if_irq_decl 15 isr_irq15
+if_irq_decl 16 isr_irq16
+if_irq_decl 17 isr_irq17
+if_irq_decl 18 isr_irq18
+if_irq_decl 19 isr_irq19
+if_irq_decl 20 isr_irq20
+if_irq_decl 21 isr_irq21
+if_irq_decl 22 isr_irq22
+if_irq_decl 23 isr_irq23
+if_irq_decl 24 isr_irq24
+if_irq_decl 25 isr_irq25
+if_irq_decl 26 isr_irq26
+if_irq_decl 27 isr_irq27
+if_irq_decl 28 isr_irq28
+if_irq_decl 29 isr_irq29
+if_irq_decl 30 isr_irq30
+if_irq_decl 31 isr_irq31
+if_irq_decl 32 isr_irq32
+if_irq_decl 33 isr_irq33
+if_irq_decl 34 isr_irq34
+if_irq_decl 35 isr_irq35
+if_irq_decl 36 isr_irq36
+if_irq_decl 37 isr_irq37
+if_irq_decl 38 isr_irq38
+if_irq_decl 39 isr_irq39
+if_irq_decl 40 isr_irq40
+if_irq_decl 41 isr_irq41
+if_irq_decl 42 isr_irq42
+if_irq_decl 43 isr_irq43
+if_irq_decl 44 isr_irq44
+if_irq_decl 45 isr_irq45
+if_irq_decl 46 isr_irq46
+if_irq_decl 47 isr_irq47
+if_irq_decl 48 isr_irq48
+if_irq_decl 49 isr_irq49
+if_irq_decl 50 isr_irq50
+if_irq_decl 51 isr_irq51
+if_irq_decl 52 isr_irq52
+if_irq_decl 53 isr_irq53
+if_irq_decl 54 isr_irq54
+if_irq_decl 55 isr_irq55
+if_irq_decl 56 isr_irq56
+if_irq_decl 57 isr_irq57
+if_irq_decl 58 isr_irq58
+if_irq_decl 59 isr_irq59
+if_irq_decl 60 isr_irq60
+if_irq_decl 61 isr_irq61
+if_irq_decl 62 isr_irq62
+if_irq_decl 63 isr_irq63
+if_irq_decl 64 isr_irq64
+if_irq_decl 65 isr_irq65
+if_irq_decl 66 isr_irq66
+if_irq_decl 67 isr_irq67
+if_irq_decl 68 isr_irq68
+if_irq_decl 69 isr_irq69
+if_irq_decl 70 isr_irq70
+if_irq_decl 71 isr_irq71
+if_irq_decl 72 isr_irq72
+if_irq_decl 73 isr_irq73
+if_irq_decl 74 isr_irq74
+if_irq_decl 75 isr_irq75
+if_irq_decl 76 isr_irq76
+if_irq_decl 77 isr_irq77
+if_irq_decl 78 isr_irq78
+if_irq_decl 79 isr_irq79
+#if NUM_IRQS > 80
+#error more IRQ entries required
+#endif
// All unhandled USER IRQs fall through to here
.global __unhandled_user_irq
diff --git a/src/rp2_common/pico_crt0/embedded_end_block.inc.S b/src/rp2_common/pico_crt0/embedded_end_block.inc.S
index 9b56633f2..2c0fa8588 100644
--- a/src/rp2_common/pico_crt0/embedded_end_block.inc.S
+++ b/src/rp2_common/pico_crt0/embedded_end_block.inc.S
@@ -1,5 +1,6 @@
#if PICO_CRT0_INCLUDE_PICOBIN_END_BLOCK
.section .embedded_end_block, "a"
+.p2align 2
embedded_end_block:
.word PICOBIN_BLOCK_MARKER_START
diff --git a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel
index d70458677..dcf727cc5 100644
--- a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel
+++ b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel
@@ -1,5 +1,14 @@
package(default_visibility = ["//visibility:public"])
+exports_files(
+ [
+ "memmap_blocked_ram.ld",
+ "memmap_copy_to_ram.ld",
+ "memmap_default.ld",
+ "memmap_no_flash.ld",
+ ]
+)
+
# It's possible to set linker scripts globally or on a per-binary basis.
#
# Setting globally:
diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld
index 175312ff9..6f5000566 100644
--- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld
+++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld
@@ -213,11 +213,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld
index 78b8a1f2b..842ebfd3c 100644
--- a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld
+++ b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld
@@ -214,11 +214,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld
index aea712a53..51254012d 100644
--- a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld
+++ b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld
@@ -213,11 +213,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld
index b9d3c3763..dbf006a8c 100644
--- a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld
+++ b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld
@@ -181,11 +181,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel
index 5c13f5a95..88cbd1032 100644
--- a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel
+++ b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel
@@ -1,5 +1,13 @@
package(default_visibility = ["//visibility:public"])
+exports_files(
+ [
+ "memmap_copy_to_ram.ld",
+ "memmap_default.ld",
+ "memmap_no_flash.ld",
+ ]
+)
+
# It's possible to set linker scripts globally or on a per-binary basis.
#
# Setting globally:
diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld
index f365682b3..89d63a9f0 100644
--- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld
+++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld
@@ -234,11 +234,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld
index ba8a113e2..bce316d14 100644
--- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld
+++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld
@@ -227,11 +227,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld
index 2febe5299..98088cdfc 100644
--- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld
+++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld
@@ -186,11 +186,10 @@ SECTIONS
__end__ = .;
end = __end__;
KEEP(*(.heap*))
- /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
- to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
- . = ORIGIN(RAM) + LENGTH(RAM);
- __HeapLimit = .;
} > RAM
+ /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
+ to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
+ __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
/* Start and end symbols must be word-aligned */
.scratch_x : {
diff --git a/src/rp2_common/pico_cyw43_arch/BUILD.bazel b/src/rp2_common/pico_cyw43_arch/BUILD.bazel
index 6484bf5b8..286184e73 100644
--- a/src/rp2_common/pico_cyw43_arch/BUILD.bazel
+++ b/src/rp2_common/pico_cyw43_arch/BUILD.bazel
@@ -2,6 +2,36 @@ load("//bazel:defs.bzl", "compatible_with_pico_w", "incompatible_with_config")
package(default_visibility = ["//visibility:public"])
+alias(
+ name = "pico_cyw43_arch",
+ actual = select({
+ "//bazel/constraint:pico_lwip_config_unset": ":select_no_lwip",
+ "//conditions:default": ":select_lwip",
+ })
+)
+
+alias(
+ name = "select_lwip",
+ actual = select({
+ "//bazel/constraint:pico_async_context_poll_enabled": ":pico_cyw43_arch_lwip_poll",
+ "//bazel/constraint:pico_async_context_threadsafe_background_enabled": ":pico_cyw43_arch_lwip_threadsafe_background",
+ "//bazel/constraint:pico_async_context_freertos_enabled": ":pico_cyw43_arch_lwip_freertos",
+ "//conditions:default": "//bazel:incompatible_cc_lib",
+ }),
+ visibility = ["//visibility:private"],
+)
+
+alias(
+ name = "select_no_lwip",
+ actual = select({
+ "//bazel/constraint:pico_async_context_poll_enabled": ":pico_cyw43_arch_poll",
+ "//bazel/constraint:pico_async_context_threadsafe_background_enabled": ":pico_cyw43_arch_threadsafe_background",
+ "//bazel/constraint:pico_async_context_freertos_enabled": ":pico_cyw43_arch_freertos",
+ "//conditions:default": "//bazel:incompatible_cc_lib",
+ }),
+ visibility = ["//visibility:private"],
+)
+
# Tuple is async_context type and whether or not lwip is enabled.
_CONFIGURATIONS = [
("freertos", False),
@@ -13,8 +43,8 @@ _CONFIGURATIONS = [
]
# This produces the following labels:
-# pico_cyw43_arch_sys_freertos
-# pico_cyw43_arch_lwip_sys_freertos
+# pico_cyw43_arch_freertos
+# pico_cyw43_arch_lwip_freertos
# pico_cyw43_arch_poll
# pico_cyw43_arch_lwip_poll
# pico_cyw43_arch_threadsafe_background
@@ -36,20 +66,24 @@ _CONFIGURATIONS = [
defines = [
"LIB_PICO_CYW43_ARCH=1",
"PICO_CYW43_ARCH_{}=1".format(kind.upper()),
- "CYW43_LWIP={}".format(1 if use_lwip else 0),
],
includes = ["include"],
target_compatible_with = compatible_with_pico_w() + (
incompatible_with_config("//bazel/constraint:pico_freertos_unset") if kind == "freertos" else []
+ ) + (
+ incompatible_with_config("//bazel/constraint:pico_lwip_config_unset") if use_lwip else []
),
deps = [
"//src/rp2_common:pico_platform",
"//src/rp2_common/pico_async_context:pico_async_context_{}".format(kind),
"//src/rp2_common/pico_cyw43_driver",
- "//src/rp2_common/pico_lwip",
"//src/rp2_common/pico_unique_id",
] + (
- ["//src/rp2_common/pico_lwip:pico_lwip_freertos"] if kind == "freertos" else ["//src/rp2_common/pico_lwip:pico_lwip_nosys"]
+ ["//src/rp2_common/pico_lwip:pico_lwip_freertos"] if kind == "freertos" and use_lwip else []
+ ) + (
+ ["//src/rp2_common/pico_lwip:pico_lwip_nosys"] if kind != "freertos" and use_lwip else []
+ ) + (
+ ["//src/rp2_common/pico_lwip"] if use_lwip else []
),
)
for kind, use_lwip in _CONFIGURATIONS
diff --git a/src/rp2_common/pico_cyw43_driver/BUILD.bazel b/src/rp2_common/pico_cyw43_driver/BUILD.bazel
index f99018c93..23bec36a7 100644
--- a/src/rp2_common/pico_cyw43_driver/BUILD.bazel
+++ b/src/rp2_common/pico_cyw43_driver/BUILD.bazel
@@ -16,16 +16,10 @@ cc_library(
cc_library(
name = "pico_cyw43_driver",
srcs = [
- "btstack_chipset_cyw43.c",
- "btstack_cyw43.c",
- "btstack_hci_transport_cyw43.c",
"cyw43_bus_pio_spi.c",
"cyw43_driver.c",
],
hdrs = [
- "include/pico/btstack_chipset_cyw43.h",
- "include/pico/btstack_cyw43.h",
- "include/pico/btstack_hci_transport_cyw43.h",
"include/pico/cyw43_driver.h",
],
includes = ["include"],
@@ -33,7 +27,7 @@ cc_library(
deps = [
":cyw43_bus_pio",
":cyw43_configport",
- "//bazel/config:PICO_BTSTACK_CONFIG",
+ ":pico_btstack_cyw43",
"//src/rp2_common:pico_platform",
"//src/rp2_common/hardware_clocks",
"//src/rp2_common/hardware_dma",
@@ -41,12 +35,48 @@ cc_library(
"//src/rp2_common/hardware_pio",
"//src/rp2_common/hardware_sync",
"//src/rp2_common/pico_async_context",
- "//src/rp2_common/pico_btstack:btstack_run_loop_async_context",
- "//src/rp2_common/pico_btstack:pico_btstack_base",
- "//src/rp2_common/pico_btstack:pico_btstack_flash_bank",
"//src/rp2_common/pico_unique_id",
"@cyw43-driver//:cyw43_driver",
+ ] + select({
+ "//bazel/constraint:pico_btstack_config_unset": [],
+ "//conditions:default": [
+ "//src/rp2_common/pico_btstack:pico_btstack",
+ ],
+ }),
+ alwayslink = True,
+)
+
+cc_library(
+ name = "pico_btstack_cyw43",
+ srcs = select({
+ "//bazel/constraint:pico_btstack_config_unset": [],
+ "//conditions:default": [
+ "btstack_cyw43.c",
+ "btstack_chipset_cyw43.c",
+ "btstack_hci_transport_cyw43.c",
+ ],
+ }),
+ hdrs = [
+ "include/pico/btstack_chipset_cyw43.h",
+ "include/pico/btstack_cyw43.h",
+ "include/pico/btstack_hci_transport_cyw43.h",
],
+ includes = ["include"],
+ deps = [
+ ":cyw43_bus_pio",
+ ":cyw43_configport",
+ "@cyw43-driver//:cyw43_driver",
+ ] + select({
+ "//bazel/constraint:pico_btstack_config_unset": [],
+ "//conditions:default": [
+ "//bazel/config:PICO_BTSTACK_CONFIG",
+ "//src/rp2_common/pico_cyw43_driver/cybt_shared_bus:cybt_shared_bus_driver",
+ "//src/rp2_common/pico_btstack:btstack_run_loop_async_context",
+ "//src/rp2_common/pico_btstack:pico_btstack",
+ "//src/rp2_common/pico_btstack:pico_btstack_flash_bank",
+ ],
+ }),
+ alwayslink = True,
)
pico_generate_pio_header(
diff --git a/src/rp2_common/pico_cyw43_driver/CMakeLists.txt b/src/rp2_common/pico_cyw43_driver/CMakeLists.txt
index eba583328..289a22ab4 100644
--- a/src/rp2_common/pico_cyw43_driver/CMakeLists.txt
+++ b/src/rp2_common/pico_cyw43_driver/CMakeLists.txt
@@ -55,6 +55,47 @@ if (EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
hardware_dma
hardware_exception
)
+ # commented out as I don't think there is a major use case for these to be settable from CMake command line vs board header, or target_compile_defitions
+# if (CYW43_PIN_WL_DYNAMIC)
+# # PICO_CMAKE_CONFIG: CYW43_PIN_WL_DYNAMIC, flag to indicate if cyw43 SPI pins can be changed at runtime, type=bool, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_PIN_WL_DYNAMIC=${CYW43_PIN_WL_DYNAMIC})
+# endif()
+# if (CYW43_DEFAULT_PIN_WL_REG_ON)
+# # PICO_CMAKE_CONFIG: CYW43_DEFAULT_PIN_WL_REG_ON, gpio pin to power up the cyw43 chip, type=int, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_DEFAULT_PIN_WL_REG_ON=${CYW43_DEFAULT_PIN_WL_REG_ON})
+# endif()
+# if (CYW43_DEFAULT_PIN_WL_DATA_OUT)
+# # PICO_CMAKE_CONFIG: CYW43_DEFAULT_PIN_WL_DATA_OUT, gpio pin for spi data out to the cyw43 chip, type=int, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_DEFAULT_PIN_WL_DATA_OUT=${CYW43_DEFAULT_PIN_WL_DATA_OUT})
+# endif()
+# if (CYW43_DEFAULT_PIN_WL_DATA_IN)
+# # PICO_CMAKE_CONFIG: CYW43_DEFAULT_PIN_WL_DATA_IN, gpio pin for spi data in from the cyw43 chip, type=int, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_DEFAULT_PIN_WL_DATA_IN=${CYW43_DEFAULT_PIN_WL_DATA_IN})
+# endif()
+# if (CYW43_DEFAULT_PIN_WL_HOST_WAKE)
+# # PICO_CMAKE_CONFIG: CYW43_DEFAULT_PIN_WL_HOST_WAKE, gpio (irq) pin for the irq line from the cyw43 chip, type=int, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_DEFAULT_PIN_WL_HOST_WAKE=${CYW43_DEFAULT_PIN_WL_HOST_WAKE})
+# endif()
+# if (CYW43_DEFAULT_PIN_WL_CLOCK)
+# # PICO_CMAKE_CONFIG: CYW43_DEFAULT_PIN_WL_CLOCK, gpio pin for the spi clock line to the cyw43 chip, type=int, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_DEFAULT_PIN_WL_CLOCK=${CYW43_DEFAULT_PIN_WL_CLOCK})
+# endif()
+# if (CYW43_DEFAULT_PIN_WL_CS)
+# # PICO_CMAKE_CONFIG: CYW43_DEFAULT_PIN_WL_CS, gpio pin for the spi chip select to the cyw43 chip, type=int, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_DEFAULT_PIN_WL_CS=${CYW43_DEFAULT_PIN_WL_CS})
+# endif()
+# if (CYW43_PIO_CLOCK_DIV_INT)
+# # PICO_CMAKE_CONFIG: CYW43_PIO_CLOCK_DIV_INT, integer component of pio clock divider used for cyw43 comms, type=int, default=2, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_PIO_CLOCK_DIV_INT=${CYW43_PIO_CLOCK_DIV_INT})
+# endif()
+# if (CYW43_PIO_CLOCK_DIV_FRAC8)
+# # PICO_CMAKE_CONFIG: CYW43_PIO_CLOCK_DIV_FRAC8, fractional component of pio clock divider used for cyw43 comms in range 0-255, type=int, default=0, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_PIO_CLOCK_DIV_FRAC8=${CYW43_PIO_CLOCK_DIV_FRAC8})
+# endif()
+# if (CYW43_PIO_CLOCK_DIV_DYNAMIC)
+# # PICO_CMAKE_CONFIG: CYW43_PIO_CLOCK_DIV_DYNAMIC, flag used to enable dynamic pio clock divider API, type=bool, default=0, group=pico_cyw43_driver
+# target_compile_definitions(cyw43_driver_picow INTERFACE CYW43_PIO_CLOCK_DIV_DYNAMIC=${CYW43_PIO_CLOCK_DIV_DYNAMIC})
+# endif()
# Note: This is used by MP, so check for issues when making changes
# e.g. Don't add new depenedences
@@ -92,12 +133,13 @@ if (EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
# Set an ip address in a compile definition
# target name, target type, compile definition name to set then address in a string
# This can be used to set the following compile definitions
- # CYW43_DEFAULT_IP_ADDRESS
+ # CYW43_DEFAULT_IP_STA_ADDRESS
+ # CYW43_DEFAULT_IP_STA_GATEWAY
+ # CYW43_DEFAULT_IP_AP_ADDRESS
+ # CYW43_DEFAULT_IP_AP_GATEWAY
# CYW43_DEFAULT_IP_MASK
- # CYW43_DEFAULT_IP_GATEWAY
# CYW43_DEFAULT_IP_DNS
- # CYW43_DEFAULT_AP_IP_ADDRESS
- # e.g. pico_configure_ip4_address(picow_tcpip_server_background PRIVATE CYW43_DEFAULT_IP_ADDRESS "10.3.15.204")
+ # e.g. pico_configure_ip4_address(picow_tcpip_server_background PRIVATE CYW43_DEFAULT_IP_STA_ADDRESS "10.3.15.204")
function(pico_configure_ip4_address TARGET_LIB TARGET_TYPE DEF_NAME IP_ADDRESS_STR)
string(REGEX MATCHALL "[0-9]+" IP_ADDRESS_LIST ${IP_ADDRESS_STR})
list(LENGTH IP_ADDRESS_LIST IP_ADDRESS_COMPONENT_COUNT)
diff --git a/src/rp2_common/pico_cyw43_driver/btstack_hci_transport_cyw43.c b/src/rp2_common/pico_cyw43_driver/btstack_hci_transport_cyw43.c
index c0210b651..ecfcf3dbe 100644
--- a/src/rp2_common/pico_cyw43_driver/btstack_hci_transport_cyw43.c
+++ b/src/rp2_common/pico_cyw43_driver/btstack_hci_transport_cyw43.c
@@ -139,6 +139,9 @@ static void hci_transport_cyw43_process(void) {
CYW43_THREAD_LOCK_CHECK
uint32_t len = 0;
bool has_work;
+#ifdef PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT
+ uint32_t loop_count = 0;
+#endif
do {
int err = cyw43_bluetooth_hci_read(hci_packet_with_pre_buffer, sizeof(hci_packet_with_pre_buffer), &len);
BT_DEBUG("bt in len=%lu err=%d\n", len, err);
@@ -148,6 +151,12 @@ static void hci_transport_cyw43_process(void) {
} else {
has_work = false;
}
+// PICO_CONFIG: PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT, limit the max number of iterations of the hci processing loop, type=int, advanced=true, group=pico_btstack
+#ifdef PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT
+ if (++loop_count >= PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT) {
+ break;
+ }
+#endif
} while (has_work);
}
diff --git a/src/rp2_common/pico_cyw43_driver/cybt_shared_bus/BUILD.bazel b/src/rp2_common/pico_cyw43_driver/cybt_shared_bus/BUILD.bazel
index a1e24b0df..24e53b3f9 100644
--- a/src/rp2_common/pico_cyw43_driver/cybt_shared_bus/BUILD.bazel
+++ b/src/rp2_common/pico_cyw43_driver/cybt_shared_bus/BUILD.bazel
@@ -11,4 +11,5 @@ cc_library(
deps = [
"@cyw43-driver//:cyw43_driver",
],
+ alwayslink = True,
)
diff --git a/src/rp2_common/pico_cyw43_driver/cyw43-driver.BUILD b/src/rp2_common/pico_cyw43_driver/cyw43-driver.BUILD
index 99b6faebf..582faa6d3 100644
--- a/src/rp2_common/pico_cyw43_driver/cyw43-driver.BUILD
+++ b/src/rp2_common/pico_cyw43_driver/cyw43-driver.BUILD
@@ -11,7 +11,21 @@ cc_library(
"src/cyw43_stats.c",
],
hdrs = glob(["**/*.h"]),
- defines = ["CYW43_ENABLE_BLUETOOTH=1"],
+ defines = select({
+ "@pico-sdk//bazel/constraint:pico_lwip_config_unset": [
+ "CYW43_LWIP=0",
+ ],
+ "//conditions:default": [
+ "CYW43_LWIP=1",
+ ],
+ })+ select({
+ "@pico-sdk//bazel/constraint:pico_btstack_config_unset": [
+ "CYW43_ENABLE_BLUETOOTH=0",
+ ],
+ "//conditions:default": [
+ "CYW43_ENABLE_BLUETOOTH=1",
+ ],
+ }),
includes = [
"firmware",
"src",
@@ -19,6 +33,10 @@ cc_library(
target_compatible_with = compatible_with_pico_w(),
deps = [
"@pico-sdk//src/rp2_common/pico_cyw43_driver:cyw43_configport",
- "@pico-sdk//src/rp2_common/pico_lwip",
- ],
+ ] + select({
+ "@pico-sdk//bazel/constraint:pico_lwip_config_unset": [],
+ "//conditions:default": [
+ "@pico-sdk//src/rp2_common/pico_lwip",
+ ],
+ }),
)
diff --git a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
index 0339571dd..bcc7284f1 100644
--- a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
+++ b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
@@ -21,15 +21,15 @@
#include "pico/cyw43_driver.h"
#if CYW43_SPI_PIO
-#define WL_REG_ON 23
-#define DATA_OUT_PIN 24u
-#define DATA_IN_PIN 24u
-#define IRQ_PIN 24u
-// #define MONITOR_PIN 3u
-#define CLOCK_PIN 29u
-#define CS_PIN 25u
+
#define IRQ_SAMPLE_DELAY_NS 100
+#if !CYW43_PIN_WL_DYNAMIC && PICO_PIO_USE_GPIO_BASE
+// The pins should all work in the same gpio base
+static_assert((CYW43_PIN_WL_DATA_OUT < 32 && CYW43_PIN_WL_DATA_IN < 32 && CYW43_PIN_WL_CLOCK < 32) ||
+ (CYW43_PIN_WL_DATA_OUT >= 16 && CYW43_PIN_WL_DATA_IN >= 16 && CYW43_PIN_WL_CLOCK >= 16), "");
+#endif
+
#ifdef CYW43_SPI_PROGRAM_NAME
#define SPI_PROGRAM_NAME CYW43_SPI_PROGRAM_NAME
#else
@@ -43,14 +43,14 @@
#if !CYW43_PIO_CLOCK_DIV_DYNAMIC
#define cyw43_pio_clock_div_int CYW43_PIO_CLOCK_DIV_INT
-#define cyw43_pio_clock_div_frac CYW43_PIO_CLOCK_DIV_FRAC
+#define cyw43_pio_clock_div_frac8 CYW43_PIO_CLOCK_DIV_FRAC8
#else
-static uint16_t cyw43_pio_clock_div_int = CYW43_PIO_CLOCK_DIV_INT;
-static uint8_t cyw43_pio_clock_div_frac = CYW43_PIO_CLOCK_DIV_FRAC;
+static uint32_t cyw43_pio_clock_div_int = CYW43_PIO_CLOCK_DIV_INT;
+static uint8_t cyw43_pio_clock_div_frac8 = CYW43_PIO_CLOCK_DIV_FRAC8;
-void cyw43_set_pio_clock_divisor(uint16_t clock_div_int, uint8_t clock_div_frac) {
+void cyw43_set_pio_clkdiv_int_frac8(uint32_t clock_div_int, uint8_t clock_div_frac8) {
cyw43_pio_clock_div_int = clock_div_int;
- cyw43_pio_clock_div_frac = clock_div_frac;
+ cyw43_pio_clock_div_frac8 = clock_div_frac8;
}
#endif
@@ -80,21 +80,23 @@ static uint32_t counter = 0;
//#define SWAP32(A) ((((A) & 0xff000000U) >> 8) | (((A) & 0xff0000U) << 8) | (((A) & 0xff00U) >> 8) | (((A) & 0xffU) << 8))
__force_inline static uint32_t __swap16x2(uint32_t a) {
+#ifndef __riscv
pico_default_asm ("rev16 %0, %0" : "+l" (a) : : );
+#else
+ uint32_t tmp;
+ pico_default_asm (
+ "rev8 %1, %0\n"
+ "rori %0, %1, 16\n"
+ : "+l" (a), "=l" (tmp));
+#endif
return a;
}
#define SWAP32(a) __swap16x2(a)
-#ifndef CYW43_SPI_PIO_PREFERRED_PIO
-#define CYW43_SPI_PIO_PREFERRED_PIO 1
-#endif
-static_assert(CYW43_SPI_PIO_PREFERRED_PIO >=0 && CYW43_SPI_PIO_PREFERRED_PIO < NUM_PIOS, "");
-
typedef struct {
- pio_hw_t *pio;
- uint8_t pio_func_sel;
- int8_t pio_offset;
- int8_t pio_sm;
+ PIO pio;
+ uint pio_offset;
+ uint pio_sm;
int8_t dma_out;
int8_t dma_in;
} bus_data_t;
@@ -105,65 +107,46 @@ int cyw43_spi_init(cyw43_int_t *self) {
// Only does something if CYW43_LOGIC_DEBUG=1
logic_debug_init();
- static_assert(NUM_PIOS == 2 || NUM_PIOS == 3, "");
-
-#if NUM_PIOS == 2
- pio_hw_t *pios[NUM_PIOS] = {pio0, pio1};
-#else
- pio_hw_t *pios[NUM_PIOS] = {pio0, pio1, pio2};
-#endif
- uint pio_index = CYW43_SPI_PIO_PREFERRED_PIO;
- // Check we can add the program
- for(uint i=1; i < NUM_PIOS;i++) {
- if (pio_can_add_program(pios[pio_index], &SPI_PROGRAM_FUNC)) break;
- if (i == NUM_PIOS - 1) {
- return CYW43_FAIL_FAST_CHECK(-CYW43_EIO);
- }
- pio_index = (pio_index + 1 ) % NUM_PIOS;
- }
assert(!self->bus_data);
self->bus_data = &bus_data_instance;
bus_data_t *bus_data = (bus_data_t *)self->bus_data;
- bus_data->pio = pios[pio_index];
+ bus_data->pio = NULL;
bus_data->dma_in = -1;
bus_data->dma_out = -1;
- static_assert(GPIO_FUNC_PIO1 == GPIO_FUNC_PIO0 + 1, "");
- bus_data->pio_func_sel = GPIO_FUNC_PIO0 + pio_index;
- bus_data->pio_sm = (int8_t)pio_claim_unused_sm(bus_data->pio, false);
- if (bus_data->pio_sm < 0) {
+ const uint min_gpio = MIN(CYW43_PIN_WL_CLOCK, MIN(CYW43_PIN_WL_DATA_IN, CYW43_PIN_WL_DATA_OUT));
+ const uint max_gpio = MAX(CYW43_PIN_WL_CLOCK, MAX(CYW43_PIN_WL_DATA_IN, CYW43_PIN_WL_DATA_OUT));
+ if (!pio_claim_free_sm_and_add_program_for_gpio_range(&SPI_PROGRAM_FUNC, &bus_data->pio, &bus_data->pio_sm, &bus_data->pio_offset, min_gpio, max_gpio - min_gpio + 1, true)) {
cyw43_spi_deinit(self);
return CYW43_FAIL_FAST_CHECK(-CYW43_EIO);
}
-
- bus_data->pio_offset = pio_add_program(bus_data->pio, &SPI_PROGRAM_FUNC);
pio_sm_config config = SPI_PROGRAM_GET_DEFAULT_CONFIG_FUNC(bus_data->pio_offset);
- sm_config_set_clkdiv_int_frac(&config, cyw43_pio_clock_div_int, cyw43_pio_clock_div_frac);
- hw_write_masked(&pads_bank0_hw->io[CLOCK_PIN],
+ sm_config_set_clkdiv_int_frac8(&config, cyw43_pio_clock_div_int, cyw43_pio_clock_div_frac8);
+ hw_write_masked(&pads_bank0_hw->io[CYW43_PIN_WL_CLOCK],
(uint)PADS_DRIVE_STRENGTH << PADS_BANK0_GPIO0_DRIVE_LSB,
PADS_BANK0_GPIO0_DRIVE_BITS
);
- hw_write_masked(&pads_bank0_hw->io[CLOCK_PIN],
+ hw_write_masked(&pads_bank0_hw->io[CYW43_PIN_WL_CLOCK],
(uint)1 << PADS_BANK0_GPIO0_SLEWFAST_LSB,
PADS_BANK0_GPIO0_SLEWFAST_BITS
);
- sm_config_set_out_pins(&config, DATA_OUT_PIN, 1);
- sm_config_set_in_pins(&config, DATA_IN_PIN);
- sm_config_set_set_pins(&config, DATA_OUT_PIN, 1);
+ sm_config_set_out_pins(&config, CYW43_PIN_WL_DATA_OUT, 1);
+ sm_config_set_in_pins(&config, CYW43_PIN_WL_DATA_IN);
+ sm_config_set_set_pins(&config, CYW43_PIN_WL_DATA_OUT, 1);
sm_config_set_sideset(&config, 1, false, false);
- sm_config_set_sideset_pins(&config, CLOCK_PIN);
+ sm_config_set_sideset_pins(&config, CYW43_PIN_WL_CLOCK);
sm_config_set_in_shift(&config, false, true, 32);
sm_config_set_out_shift(&config, false, true, 32);
- hw_set_bits(&bus_data->pio->input_sync_bypass, 1u << DATA_IN_PIN);
+ hw_set_bits(&bus_data->pio->input_sync_bypass, 1u << (CYW43_PIN_WL_DATA_IN - pio_get_gpio_base(bus_data->pio)));
pio_sm_set_config(bus_data->pio, bus_data->pio_sm, &config);
- pio_sm_set_consecutive_pindirs(bus_data->pio, bus_data->pio_sm, CLOCK_PIN, 1, true);
- gpio_set_function(DATA_OUT_PIN, bus_data->pio_func_sel);
+ pio_sm_set_consecutive_pindirs(bus_data->pio, bus_data->pio_sm, CYW43_PIN_WL_CLOCK, 1, true);
+ gpio_set_function(CYW43_PIN_WL_DATA_OUT, pio_get_funcsel(bus_data->pio));
// Set data pin to pull down and schmitt
- gpio_set_pulls(DATA_IN_PIN, false, true);
- gpio_set_input_hysteresis_enabled(DATA_IN_PIN, true);
+ gpio_set_pulls(CYW43_PIN_WL_DATA_IN, false, true);
+ gpio_set_input_hysteresis_enabled(CYW43_PIN_WL_DATA_IN, true);
pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_set(pio_pins, 1));
@@ -179,10 +162,9 @@ int cyw43_spi_init(cyw43_int_t *self) {
void cyw43_spi_deinit(cyw43_int_t *self) {
if (self->bus_data) {
bus_data_t *bus_data = (bus_data_t *)self->bus_data;
- if (bus_data->pio_sm >= 0) {
- if (bus_data->pio_offset != -1)
- pio_remove_program(bus_data->pio, &SPI_PROGRAM_FUNC, bus_data->pio_offset);
- pio_sm_unclaim(bus_data->pio, bus_data->pio_sm);
+ if (bus_data->pio) {
+ pio_remove_program_and_unclaim_sm(&SPI_PROGRAM_FUNC, bus_data->pio, bus_data->pio_sm, bus_data->pio_offset);
+ bus_data->pio = NULL;
}
if (bus_data->dma_out >= 0) {
dma_channel_cleanup(bus_data->dma_out);
@@ -199,7 +181,7 @@ void cyw43_spi_deinit(cyw43_int_t *self) {
}
static void cs_set(bool value) {
- gpio_put(CS_PIN, value);
+ gpio_put(CYW43_PIN_WL_CS, value);
}
static __noinline void ns_delay(uint32_t ns) {
@@ -210,9 +192,9 @@ static __noinline void ns_delay(uint32_t ns) {
static void start_spi_comms(cyw43_int_t *self) {
bus_data_t *bus_data = (bus_data_t *)self->bus_data;
- gpio_set_function(DATA_OUT_PIN, bus_data->pio_func_sel);
- gpio_set_function(CLOCK_PIN, bus_data->pio_func_sel);
- gpio_pull_down(CLOCK_PIN);
+ gpio_set_function(CYW43_PIN_WL_DATA_OUT, pio_get_funcsel(bus_data->pio));
+ gpio_set_function(CYW43_PIN_WL_CLOCK, pio_get_funcsel(bus_data->pio));
+ gpio_pull_down(CYW43_PIN_WL_CLOCK);
// Pull CS low
cs_set(false);
}
@@ -268,7 +250,7 @@ int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, u
pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
pio_sm_set_wrap(bus_data->pio, bus_data->pio_sm, bus_data->pio_offset, bus_data->pio_offset + SPI_OFFSET_END - 1);
pio_sm_clear_fifos(bus_data->pio, bus_data->pio_sm);
- pio_sm_set_pindirs_with_mask(bus_data->pio, bus_data->pio_sm, 1u << DATA_OUT_PIN, 1u << DATA_OUT_PIN);
+ pio_sm_set_pindirs_with_mask64(bus_data->pio, bus_data->pio_sm, 1ull << CYW43_PIN_WL_DATA_OUT, 1ull << CYW43_PIN_WL_DATA_OUT);
pio_sm_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_clkdiv_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_put(bus_data->pio, bus_data->pio_sm, tx_length * 8 - 1);
@@ -310,7 +292,7 @@ int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, u
pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
pio_sm_set_wrap(bus_data->pio, bus_data->pio_sm, bus_data->pio_offset, bus_data->pio_offset + SPI_OFFSET_LP1_END - 1);
pio_sm_clear_fifos(bus_data->pio, bus_data->pio_sm);
- pio_sm_set_pindirs_with_mask(bus_data->pio, bus_data->pio_sm, 1u << DATA_OUT_PIN, 1u << DATA_OUT_PIN);
+ pio_sm_set_pindirs_with_mask64(bus_data->pio, bus_data->pio_sm, 1ull << CYW43_PIN_WL_DATA_OUT, 1ull << CYW43_PIN_WL_DATA_OUT);
pio_sm_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_clkdiv_restart(bus_data->pio, bus_data->pio_sm);
pio_sm_put(bus_data->pio, bus_data->pio_sm, tx_length * 8 - 1);
@@ -334,7 +316,7 @@ int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, u
}
__compiler_memory_barrier();
pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
- pio_sm_set_consecutive_pindirs(bus_data->pio, bus_data->pio_sm, DATA_IN_PIN, 1, false);
+ pio_sm_set_consecutive_pindirs(bus_data->pio, bus_data->pio_sm, CYW43_PIN_WL_DATA_IN, 1, false);
} else if (rx != NULL) { /* currently do one at a time */
DUMP_SPI_TRANSACTIONS(
printf("[%lu] bus TX %u bytes:", counter++, rx_length);
@@ -356,32 +338,32 @@ int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, u
// Initialise our gpios
void cyw43_spi_gpio_setup(void) {
- // Setup WL_REG_ON (23)
- gpio_init(WL_REG_ON);
- gpio_set_dir(WL_REG_ON, GPIO_OUT);
- gpio_pull_up(WL_REG_ON);
+ // Setup CYW43_PIN_WL_REG_ON (23)
+ gpio_init(CYW43_PIN_WL_REG_ON);
+ gpio_set_dir(CYW43_PIN_WL_REG_ON, GPIO_OUT);
+ gpio_pull_up(CYW43_PIN_WL_REG_ON);
// Setup DO, DI and IRQ (24)
- gpio_init(DATA_OUT_PIN);
- gpio_set_dir(DATA_OUT_PIN, GPIO_OUT);
- gpio_put(DATA_OUT_PIN, false);
+ gpio_init(CYW43_PIN_WL_DATA_OUT);
+ gpio_set_dir(CYW43_PIN_WL_DATA_OUT, GPIO_OUT);
+ gpio_put(CYW43_PIN_WL_DATA_OUT, false);
// Setup CS (25)
- gpio_init(CS_PIN);
- gpio_set_dir(CS_PIN, GPIO_OUT);
- gpio_put(CS_PIN, true);
+ gpio_init(CYW43_PIN_WL_CS);
+ gpio_set_dir(CYW43_PIN_WL_CS, GPIO_OUT);
+ gpio_put(CYW43_PIN_WL_CS, true);
}
// Reset wifi chip
void cyw43_spi_reset(void) {
- gpio_put(WL_REG_ON, false); // off
+ gpio_put(CYW43_PIN_WL_REG_ON, false); // off
sleep_ms(20);
- gpio_put(WL_REG_ON, true); // on
+ gpio_put(CYW43_PIN_WL_REG_ON, true); // on
sleep_ms(250);
// Setup IRQ (24) - also used for DO, DI
- gpio_init(IRQ_PIN);
- gpio_set_dir(IRQ_PIN, GPIO_IN);
+ gpio_init(CYW43_PIN_WL_HOST_WAKE);
+ gpio_set_dir(CYW43_PIN_WL_HOST_WAKE, GPIO_IN);
}
static inline uint32_t make_cmd(bool write, bool inc, uint32_t fn, uint32_t addr, uint32_t sz) {
@@ -568,3 +550,54 @@ int cyw43_write_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len,
}
}
#endif
+
+#if CYW43_PIN_WL_DYNAMIC
+
+// storage for cyw43 pins
+static uint cyw43_pin_array[CYW43_PIN_INDEX_WL_COUNT] = {
+ CYW43_DEFAULT_PIN_WL_REG_ON,
+ CYW43_DEFAULT_PIN_WL_DATA_OUT,
+ CYW43_DEFAULT_PIN_WL_DATA_IN,
+ CYW43_DEFAULT_PIN_WL_HOST_WAKE,
+ CYW43_DEFAULT_PIN_WL_CLOCK,
+ CYW43_DEFAULT_PIN_WL_CS
+};
+
+// Check the cyw43 gpio pin array is valid
+static bool cyw43_pins_valid(uint pins[CYW43_PIN_INDEX_WL_COUNT]) {
+ // check the gpios are valid
+ for(int i = 0; i < CYW43_PIN_INDEX_WL_COUNT; i++) {
+ if (pins[i] >= NUM_BANK0_GPIOS) {
+ return false;
+ }
+ }
+#if PICO_PIO_USE_GPIO_BASE
+ // These pins should use the same gpio base
+ return (pins[CYW43_PIN_INDEX_WL_DATA_OUT] < 32 && pins[CYW43_PIN_INDEX_WL_DATA_IN] < 32 && pins[CYW43_PIN_INDEX_WL_CLOCK] < 32) ||
+ (pins[CYW43_PIN_INDEX_WL_DATA_OUT] >= 16 && pins[CYW43_PIN_INDEX_WL_DATA_IN] >= 16 && pins[CYW43_PIN_INDEX_WL_CLOCK] >= 16);
+#else
+ return true;
+#endif
+}
+
+// Set the gpio pin array
+int cyw43_set_pins_wl(uint pins[CYW43_PIN_INDEX_WL_COUNT]) {
+ assert(!bus_data_instance.pio);
+ if (bus_data_instance.pio) {
+ return PICO_ERROR_RESOURCE_IN_USE;
+ }
+ assert(cyw43_pins_valid(pins));
+ if (!cyw43_pins_valid(pins)) {
+ return PICO_ERROR_INVALID_ARG;
+ }
+ memcpy(cyw43_pin_array, pins, sizeof(cyw43_pin_array));
+ return PICO_OK;
+}
+
+// Get a gpio pin
+uint cyw43_get_pin_wl(cyw43_pin_index_t pin_id) {
+ assert(pin_id < CYW43_PIN_INDEX_WL_COUNT);
+ assert(cyw43_pin_array[pin_id] < NUM_BANK0_GPIOS);
+ return cyw43_pin_array[pin_id];
+}
+#endif // CYW43_PIN_WL_DYNAMIC
diff --git a/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h b/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h
index f012d2458..f1c00c2fb 100644
--- a/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h
+++ b/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h
@@ -80,6 +80,10 @@ extern "C" {
#define CYW43_EINVAL (-PICO_ERROR_INVALID_ARG) // Invalid argument
#define CYW43_ETIMEDOUT (-PICO_ERROR_TIMEOUT) // Connection timed out
+#ifndef CYW43_WL_GPIO_COUNT
+#define CYW43_WL_GPIO_COUNT 3
+#endif
+
#define CYW43_NUM_GPIOS CYW43_WL_GPIO_COUNT
#define cyw43_hal_pin_obj_t uint
@@ -95,16 +99,45 @@ static inline uint32_t cyw43_hal_ticks_ms(void) {
return to_ms_since_boot(get_absolute_time());
}
+#if CYW43_PIN_WL_DYNAMIC
+// these are just an index into an array
+typedef enum cyw43_pin_index_t {
+ CYW43_PIN_INDEX_WL_REG_ON,
+ CYW43_PIN_INDEX_WL_DATA_OUT,
+ CYW43_PIN_INDEX_WL_DATA_IN,
+ CYW43_PIN_INDEX_WL_HOST_WAKE,
+ CYW43_PIN_INDEX_WL_CLOCK,
+ CYW43_PIN_INDEX_WL_CS,
+ CYW43_PIN_INDEX_WL_COUNT // last
+} cyw43_pin_index_t;
+#define CYW43_PIN_WL_REG_ON cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_REG_ON)
+#define CYW43_PIN_WL_DATA_OUT cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_DATA_OUT)
+#define CYW43_PIN_WL_DATA_IN cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_DATA_IN)
+#define CYW43_PIN_WL_HOST_WAKE cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_HOST_WAKE)
+#define CYW43_PIN_WL_CLOCK cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_CLOCK)
+#define CYW43_PIN_WL_CS cyw43_get_pin_wl(CYW43_PIN_INDEX_WL_CS)
+// Lookup the gpio value in an array
+uint cyw43_get_pin_wl(cyw43_pin_index_t pin_id);
+#else
+// Just return the gpio number configured at build time
+#define CYW43_PIN_WL_REG_ON CYW43_DEFAULT_PIN_WL_REG_ON
+#define CYW43_PIN_WL_DATA_OUT CYW43_DEFAULT_PIN_WL_DATA_OUT
+#define CYW43_PIN_WL_DATA_IN CYW43_DEFAULT_PIN_WL_DATA_IN
+#define CYW43_PIN_WL_HOST_WAKE CYW43_DEFAULT_PIN_WL_HOST_WAKE
+#define CYW43_PIN_WL_CLOCK CYW43_DEFAULT_PIN_WL_CLOCK
+#define CYW43_PIN_WL_CS CYW43_DEFAULT_PIN_WL_CS
+#endif // !CYW43_PIN_WL_DYNAMIC
+
static inline int cyw43_hal_pin_read(cyw43_hal_pin_obj_t pin) {
return gpio_get(pin);
}
static inline void cyw43_hal_pin_low(cyw43_hal_pin_obj_t pin) {
- gpio_clr_mask(1 << pin);
+ gpio_put(pin, false);
}
static inline void cyw43_hal_pin_high(cyw43_hal_pin_obj_t pin) {
- gpio_set_mask(1 << pin);
+ gpio_put(pin, true);
}
#define CYW43_HAL_PIN_MODE_INPUT (GPIO_IN)
diff --git a/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h b/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h
index d35363ec1..4d17c4b32 100644
--- a/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h
+++ b/src/rp2_common/pico_cyw43_driver/include/pico/cyw43_driver.h
@@ -16,6 +16,10 @@
#include "pico.h"
+#if CYW43_PIN_WL_DYNAMIC
+#include "cyw43_configport.h"
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -44,7 +48,7 @@ void cyw43_driver_deinit(struct async_context *context);
#define CYW43_PIO_CLOCK_DIV_DYNAMIC 0
#endif
-// PICO_CONFIG: CYW43_PIO_CLOCK_DIV_INT, Integer part of the clock divider for communication with the wireless chip, type=bool, default=2, group=pico_cyw43_driver
+// PICO_CONFIG: CYW43_PIO_CLOCK_DIV_INT, Integer part of the clock divider for communication with the wireless chip, type=int, default=2, group=pico_cyw43_driver
#ifndef CYW43_PIO_CLOCK_DIV_INT
// backwards compatibility using old define
#ifdef CYW43_PIO_CLOCK_DIV
@@ -54,16 +58,64 @@ void cyw43_driver_deinit(struct async_context *context);
#endif
#endif
-// PICO_CONFIG: CYW43_PIO_CLOCK_DIV_FRAC, Fractional part of the clock divider for communication with the wireless chip, type=bool, default=0, group=pico_cyw43_driver
-#ifndef CYW43_PIO_CLOCK_DIV_FRAC
-#define CYW43_PIO_CLOCK_DIV_FRAC 0
+// PICO_CONFIG: CYW43_PIO_CLOCK_DIV_FRAC8, Fractional part of the clock divider for communication with the wireless chip 0-255, type=int, min=0, max=255, default=0, group=pico_cyw43_driver
+#ifndef CYW43_PIO_CLOCK_DIV_FRAC8
+#ifdef CYW43_PIO_CLOCK_DIV_FRAC
+#define CYW43_PIO_CLOCK_DIV_FRAC8 CYW43_PIO_CLOCK_DIV_FRAC
+#else
+#define CYW43_PIO_CLOCK_DIV_FRAC8 0
+#endif
#endif
+// PICO_CONFIG: CYW43_PIN_WL_DYNAMIC, flag to indicate if cyw43 SPI pins can be changed at runtime, type=bool, advanced=true, group=pico_cyw43_driver
+
+// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_REG_ON, gpio pin to power up the cyw43 chip, type=int, min=0, max=47 on RP2350B, 29 otherwise, advanced=true, group=pico_cyw43_driver
+
+// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_DATA_OUT, gpio pin for spi data out to the cyw43 chip, type=int, min=0, max=47 on RP2350B, 29 otherwise, advanced=true, group=pico_cyw43_driver
+
+// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_DATA_IN, gpio pin for spi data in from the cyw43 chip, type=int, min=0, max=47 on RP2350B, 29 otherwise, advanced=true, group=pico_cyw43_driver
+
+// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_HOST_WAKE, gpio (irq) pin for the irq line from the cyw43 chip, type=int, min=0, max=47 on RP2350B, 29 otherwise, advanced=true, group=pico_cyw43_driver
+
+// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_CLOCK, gpio pin for the spi clock line to the cyw43 chip, type=int, min=0, max=47 on RP2350B, 29 otherwise, advanced=true, group=pico_cyw43_driver
+
+// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_CS, gpio pin for the spi chip select to the cyw43 chip, type=int, min=0, max=47 on RP2350B, 29 otherwise, advanced=true, group=pico_cyw43_driver
+
#if CYW43_PIO_CLOCK_DIV_DYNAMIC
-void cyw43_set_pio_clock_divisor(uint16_t clock_div_int, uint8_t clock_div_frac);
+/*! \brief Set the clock divisor for the cyw43 pio clock
+ * \ingroup pico_cyw43_driver
+ *
+ * SPI is used to communicate with the CYW43 device and this is implemented using a PIO running with a divisor of 2.
+ * If the system clock is changed it may be necessary to adjust for this to allow communications to succeed.
+ * This function is only available if \ref CYW43_PIO_CLOCK_DIV_DYNAMIC is true
+ *
+ * \param clock_div_int Integer part of the divisor
+ * \param clock_div_frac8 Fractional part in 1/256ths
+*/
+void cyw43_set_pio_clkdiv_int_frac8(uint32_t clock_div_int, uint8_t clock_div_frac8);
+
+// backwards compatibility
+static inline void cyw43_set_pio_clock_divisor(uint16_t clock_div_int, uint8_t clock_div_frac8) {
+ return cyw43_set_pio_clkdiv_int_frac8(clock_div_int, clock_div_frac8);
+}
+#endif
+
+#if CYW43_PIN_WL_DYNAMIC
+/*! \brief Set the gpio pins for the communication with the cyw43 device
+ * \ingroup pico_cyw43_driver
+ *
+ * Set or change the pins used to communicate with the cyw43 device
+ * This function is only available if \ref CYW43_PIN_WL_DYNAMIC is true
+ *
+ * \note The cyw43 driver should not be de-initialised before this function is called or else the behaviour is undefined.
+ *
+ * \param pins An array containing the gpio pins to use
+ * \return PICO_OK if the pin configuration could be changed and is valid
+*/
+int cyw43_set_pins_wl(uint pins[CYW43_PIN_INDEX_WL_COUNT]);
#endif
#ifdef __cplusplus
}
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/src/rp2_common/pico_flash/BUILD.bazel b/src/rp2_common/pico_flash/BUILD.bazel
index 2edc05968..0a1b3f1ee 100644
--- a/src/rp2_common/pico_flash/BUILD.bazel
+++ b/src/rp2_common/pico_flash/BUILD.bazel
@@ -2,17 +2,29 @@ load("//bazel:defs.bzl", "compatible_with_rp2")
package(default_visibility = ["//visibility:public"])
+# Picotool needs this (transitively through
+# //src/rp2_common/pico_bootrom:pico_bootrom_headers), so we can't strictly
+# constrain compatibility.
+cc_library(
+ name = "pico_flash_headers",
+ hdrs = ["include/pico/flash.h"],
+ includes = ["include"],
+ visibility = ["//src/rp2_common/pico_bootrom:__pkg__"],
+ deps = [
+ "//src:pico_platform_internal",
+ ],
+)
+
cc_library(
name = "pico_flash",
srcs = ["flash.c"],
- hdrs = ["include/pico/flash.h"],
defines = select({
"//bazel/constraint:pico_freertos_unset": ["PICO_FREERTOS_LIB=0"],
"//conditions:default": ["PICO_FREERTOS_LIB=1"],
}),
- includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
+ ":pico_flash_headers",
"//src/common/pico_time",
"//src/rp2_common:pico_platform",
"//src/rp2_common/hardware_exception",
diff --git a/src/rp2_common/pico_flash/flash.c b/src/rp2_common/pico_flash/flash.c
index 0d5606748..6a6294a78 100644
--- a/src/rp2_common/pico_flash/flash.c
+++ b/src/rp2_common/pico_flash/flash.c
@@ -9,6 +9,7 @@
#if PICO_FLASH_SAFE_EXECUTE_PICO_SUPPORT_MULTICORE_LOCKOUT
#include "pico/multicore.h"
#endif
+#include "pico/time.h"
#if PICO_FLASH_SAFE_EXECUTE_SUPPORT_FREERTOS_SMP
#include "FreeRTOS.h"
#include "task.h"
@@ -142,16 +143,14 @@ static int default_enter_safe_zone_timeout_ms(__unused uint32_t timeout_ms) {
// it only prevents the other core from also entering a critical section.
// Therefore, we must do our own handshake which starts a task on the other core and have it disable interrupts
uint core_num = get_core_num();
- // create at low priority
+ // create at low priority on other core
TaskHandle_t task_handle;
- if (pdPASS != xTaskCreate(flash_lockout_task, "flash lockout", configMINIMAL_STACK_SIZE, (void *)core_num, 0, &task_handle)) {
+ if (pdPASS != xTaskCreateAffinitySet(flash_lockout_task, "flash lockout", configMINIMAL_STACK_SIZE, (void *)core_num, 0, 1u << (core_num ^ 1), &task_handle)) {
return PICO_ERROR_INSUFFICIENT_RESOURCES;
}
lockout_state[core_num] = FREERTOS_LOCKOUT_LOCKER_WAITING;
__sev();
- // bind to other core
- vTaskCoreAffinitySet(task_handle, 1u << (core_num ^ 1));
- // and make it super high priority
+ // make it super high priority
vTaskPrioritySet(task_handle, configMAX_PRIORITIES -1);
absolute_time_t until = make_timeout_time_ms(timeout_ms);
while (lockout_state[core_num] != FREERTOS_LOCKOUT_LOCKEE_READY && !time_reached(until)) {
diff --git a/src/rp2_common/pico_float/BUILD.bazel b/src/rp2_common/pico_float/BUILD.bazel
index eac08eb87..f6aadca2d 100644
--- a/src/rp2_common/pico_float/BUILD.bazel
+++ b/src/rp2_common/pico_float/BUILD.bazel
@@ -86,6 +86,7 @@ alias(
actual = select({
"//bazel/constraint:rp2040": ":pico_float_pico",
"@platforms//cpu:armv8-m": ":pico_float_vfp",
+ "@platforms//cpu:riscv32": ":pico_float_single_hazard3",
"//conditions:default": ":pico_float_compiler",
}),
visibility = ["//visibility:private"],
@@ -138,12 +139,22 @@ _PICO_FLOAT_IMPLS = [
"extra_deps": ["//src/rp2_common/hardware_dcp"],
"linkopts": _WRAP_FLOAT_SCI_FLAGS,
},
+ {
+ "name": "single_hazard3",
+ "srcs": [
+ "float_single_hazard3.S",
+ ],
+ "compatibility": compatible_with_rp2() + ["@platforms//cpu:riscv32"],
+ "extra_deps": ["//src/rp2_common/hardware_hazard3"],
+ "linkopts": _WRAP_FLOAT_SCI_FLAGS,
+ },
]
# Creates:
# * pico_float_pico
# * pico_float_dcp
# * pico_float_vfp
+# * pico_float_single_hazard3
[
cc_library(
name = "pico_float_{}".format(impl["name"]),
diff --git a/src/rp2_common/pico_float/CMakeLists.txt b/src/rp2_common/pico_float/CMakeLists.txt
index 086628221..7d53274ff 100644
--- a/src/rp2_common/pico_float/CMakeLists.txt
+++ b/src/rp2_common/pico_float/CMakeLists.txt
@@ -10,11 +10,7 @@
# add alias "default" which is just pico.
add_library(pico_float_default INTERFACE)
- if (PICO_RISCV)
- target_link_libraries(pico_float_default INTERFACE pico_float_compiler)
- else()
- target_link_libraries(pico_float_default INTERFACE pico_float_pico)
- endif()
+ target_link_libraries(pico_float_default INTERFACE pico_float_pico)
set(PICO_DEFAULT_FLOAT_IMPL pico_float_default)
@@ -128,6 +124,10 @@
wrap_float_functions(pico_float_pico_vfp NO_WRAP_AEABI)
target_link_libraries(pico_float_pico INTERFACE
pico_float_pico_vfp)
+ else()
+ target_sources(pico_float_pico INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/float_single_hazard3.S
+ )
endif()
diff --git a/src/rp2_common/pico_float/float_single_hazard3.S b/src/rp2_common/pico_float/float_single_hazard3.S
new file mode 100644
index 000000000..ee2f1c72b
--- /dev/null
+++ b/src/rp2_common/pico_float/float_single_hazard3.S
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/asm_helper.S"
+#include "hardware/hazard3.h"
+
+// This file reimplements some common single-precision soft float routines
+// from libgcc. It targets the RV32IMBZbkb dialect (plus optionally Xh3bextm)
+// and is tuned for Hazard3 execution timings.
+
+// Subnormal values are always flushed to zero on both input and output.
+// Rounding is always to nearest (even on tie).
+
+pico_default_asm_setup
+
+.macro float_section name
+#if PICO_FLOAT_IN_RAM
+.section RAM_SECTION_NAME(\name), "ax"
+#else
+.section SECTION_NAME(\name), "ax"
+#endif
+.endm
+
+float_section __addsf3
+.global __subsf3
+.p2align 2
+__subsf3:
+ binvi a1, a1, 31
+.global __addsf3
+__addsf3:
+ // Unpack exponent:
+ h3.bextmi a2, a0, 23, 8
+ h3.bextmi a3, a1, 23, 8
+ // Flush-to-zero => 0 + y = y applies, including nan, with the sole
+ // exception of y being subnormal (which also needs to be flushed)
+ beqz a2, __addsf_return_y_flushed
+ // Don't have to handle this case for x + 0 = 0 because we already know x
+ // is nonzero
+ beqz a3, __addsf_return_x
+ // Unpack significand, plus 3 extra zeroes for working space:
+ slli a4, a0, 9
+ slli a5, a1, 9
+ // check nan/inf on input
+ li t0, 255
+ beq a2, t0, __addsf_x_nan_inf
+ beq a3, t0, __addsf_y_nan_inf
+ // (finish unpacking significand)
+ srli a4, a4, 6
+ srli a5, a5, 6
+
+ // If we're still on the straight path then we are adding two normal
+ // values. Add implicit one (1.xx...xx000)
+ bseti a4, a4, 23 + 3
+ bseti a5, a5, 23 + 3
+ // Negate if sign bit is set
+ bgez a0, 1f
+ neg a4, a4
+1:
+ // (tuck this 16-bit here to avoid alignment penalty)
+ li t1, 25
+ bgez a1, 1f
+ neg a5, a5
+1:
+
+ bltu a2, a3, __addsf_ye_gt_xe
+
+ // The main body is repeated twice with different register assignments.
+ // lhs is the more-significant addend:
+.macro addsf_core packed_lhs, packed_rhs, sig_lhs, sig_rhs, exp_lhs, exp_rhs, rhs_is_x
+ sub \packed_rhs, \exp_lhs, \exp_rhs
+ // If there is a large exponent difference then there is no effect on lhs
+.if \rhs_is_x
+ bgeu \packed_rhs, t1, __addsf_return_y
+.else
+ bgeu \packed_rhs, t1, __addsf_return_x
+.endif
+ // Shift rhs down to correct relative significance
+ sra \packed_lhs, \sig_rhs, \packed_rhs
+ // Set sticky bit if ones were shifted out
+ sll \packed_rhs, \packed_lhs, \packed_rhs
+ sltu \packed_rhs, \packed_rhs, \sig_rhs
+ or \packed_lhs, \packed_lhs, \packed_rhs
+ // Add significands
+ add \sig_lhs, \sig_lhs, \packed_lhs
+ // Detect exact cancellation (may be beyond max normalisation shift; also
+ // IEEE 754 requires +0 for exact cancellation, no matter input signs)
+ beqz \sig_lhs, __addsf_return_0
+ // Convert two's complement back to sign + magnitude
+ srai \exp_rhs, \sig_lhs, 31
+ xor \sig_lhs, \sig_lhs, \exp_rhs
+ sub \sig_lhs, \sig_lhs, \exp_rhs
+ // Renormalise significand: bit 31 is now implicit one
+ clz \packed_lhs, \sig_lhs
+ sll \sig_lhs, \sig_lhs, \packed_lhs
+ // Adjust exponent
+ addi \packed_lhs, \packed_lhs, -5
+ sub \exp_lhs, \exp_lhs, \packed_lhs
+
+ // Round to nearest, even on tie (bias upward if above odd number)
+ bexti \packed_lhs, \sig_lhs, 8
+ addi \sig_lhs, \sig_lhs, 127
+ add \sig_lhs, \sig_lhs, \packed_lhs
+ // Exponent may increase by one due to rounding up from all-ones; this is
+ // detected by clearing of implicit one (there is a carry-out too)
+ bgez \sig_lhs, 3f
+4:
+ // Detect underflow/overflow
+ bgeu \exp_lhs, t0, 1f
+
+ // Pack and return
+ packh \exp_lhs, \exp_lhs, \exp_rhs
+ slli \exp_lhs, \exp_lhs, 23
+ slli \sig_lhs, \sig_lhs, 1
+ srli \sig_lhs, \sig_lhs, 9
+ add a0, \sig_lhs, \exp_lhs
+ ret
+1:
+ bgez \exp_lhs, 2f
+ // Signed zero on underflow
+ slli a0, \exp_rhs, 31
+ ret
+2:
+ // Signed infinity on overflow
+ packh a0, t0, \exp_rhs
+ slli a0, a0, 23
+ ret
+3:
+ // Exponent increase due to rounding (uncommon)
+ srli \sig_lhs, \sig_lhs, 1
+ addi \exp_lhs, \exp_lhs, 1
+ j 4b
+.endm
+
+__addsf_xe_gte_ye:
+ addsf_core a0, a1, a4, a5, a2, a3, 0
+.p2align 2
+__addsf_ye_gt_xe:
+ addsf_core a1, a0, a5, a4, a3, a2, 1
+
+__addsf_x_nan_inf:
+ // When at least one operand is nan, we must propagate at least one of
+ // those nan payloads (sign of nan result is unspecified, which we take
+ // advantage of by implementing x - y as x + -y). Check x nan vs inf:
+ bnez a4, __addsf_return_x
+__addsf_x_inf:
+ // If x is +-inf, need to distinguish the following cases:
+ bne a3, t0, __addsf_return_x // y is neither inf nor nan -> return x (propagate inf)
+ bnez a5, __addsf_return_y // y is nan: -> return y (propagate nan)
+ xor a5, a0, a1
+ srli a5, a5, 31
+ beqz a5, __addsf_return_x // y is inf of same sign -> return either x or y (x is faster)
+ li a0, -1 // y is inf of different sign -> return nan
+ ret
+
+__addsf_y_nan_inf:
+ // Mirror of __addsf_x_nan_inf
+ bnez a5, __addsf_return_y
+__addsf_y_inf:
+ bne a2, t0, __addsf_return_y
+ bnez a4, __addsf_return_x
+ xor a4, a0, a1
+ srli a4, a4, 31
+ beqz a4, __addsf_return_x
+ li a0, -1
+ ret
+
+__addsf_return_y_flushed:
+ bnez a3, 1f
+ srli a1, a1, 23
+ slli a1, a1, 23
+1:
+__addsf_return_y:
+ mv a0, a1
+__addsf_return_x:
+ ret
+__addsf_return_0:
+ li a0, 0
+ ret
+
+
+float_section __mulsf3
+.global __mulsf3
+.p2align 2
+__mulsf3:
+ // Force y to be positive (by possibly negating x) *before* unpacking.
+ // This allows many special cases to be handled without repacking.
+ bgez a1, 1f
+ binvi a0, a0, 31
+1:
+ // Unpack exponent:
+ h3.bextmi a2, a0, 23, 8
+ h3.bextmi a3, a1, 23, 8
+ // Check special cases
+ li t0, 255
+ beqz a2, __mulsf_x_0
+ beqz a3, __mulsf_y_0
+ beq a2, t0, __mulsf_x_nan_inf
+ beq a3, t0, __mulsf_y_nan_inf
+
+ // Finish unpacking sign
+ srai a6, a0, 31
+ // Unpack significand (with implicit one in MSB)
+ slli a4, a0, 8
+ slli a5, a1, 8
+ bseti a4, a4, 31
+ bseti a5, a5, 31
+ // Get full 64-bit multiply result in a4:a1 (one cycle each half)
+ // Going from Q1.23 to Q2.46 (both left-justified)
+ mul a1, a4, a5
+ mulhu a4, a4, a5
+ // Normalise (shift left by either 0 or 1) -- bit 8 is the LSB of the
+ // final significand (ignoring rounding)
+ clz a0, a4
+ sll a4, a4, a0
+ sub a2, a2, a0
+ add a2, a2, a3
+ // Subtract redundant bias term (127), add 1 for normalisation correction
+ addi a2, a2, -126
+ blez a2, __mulsf_underflow
+
+ // Gather sticky bits from low fraction:
+ snez a1, a1
+ or a4, a4, a1
+ // Round to nearest, even on tie (aka bias upward if odd)
+ bexti a1, a4, 8
+ add a4, a4, a1
+ addi a4, a4, 127
+ // Check carry-out: exponent may increase due to rounding
+ bgez a4, 2f
+1:
+ bge a2, t0, __mulsf_overflow
+ // Pack it and ship it
+ packh a2, a2, a6
+ slli a2, a2, 23
+ slli a4, a4, 1
+ srli a4, a4, 9
+ add a0, a4, a2
+ ret
+2:
+ srli a4, a4, 1
+ addi a2, a2, 1
+ j 1b
+
+__mulsf_underflow:
+ // Signed zero
+ slli a0, a6, 31
+ ret
+__mulsf_overflow:
+ // Signed inf
+ packh a0, t0, a6
+ slli a0, a0, 23
+ ret
+
+__mulsf_x_0:
+ // 0 times nan -> propagate nan
+ // 0 times inf -> generate nan
+ // 0 times others -> 0 (need to flush significand too as we are FTZ)
+ bne a3, t0, __mulsf_return_flushed_x
+ slli a5, a1, 9
+ beqz a5, 1f
+ // Propagate nan from y
+__mulsf_return_y:
+ mv a0, a1
+ ret
+1:
+ // Generate new nan
+ li a0, -1
+ ret
+
+__mulsf_y_0:
+ // Mirror image of x_0 except we still return x for signed 0, since the
+ // signs were already resolved.
+ bne a2, t0, __mulsf_return_flushed_x
+ slli a1, a0, 9
+ bnez a1, 1f
+ li a0, -1
+1:
+ ret
+
+__mulsf_return_flushed_x:
+ // If we don't support subnormals we at least need to flush to a canonical
+ // zero. This is just a sign bit in bit 31.
+ srli a0, a0, 31
+ slli a0, a0, 31
+__mulsf_return_x:
+ ret
+
+__mulsf_x_nan_inf:
+ // We know that y is not zero and is positive. So...
+ // x is nan -> return x
+ // else y is nan -> return y
+ // else y is inf -> return x
+ // else y is normal -> return x
+ // (the order of the first two clauses is actually our free choice)
+ slli a4, a0, 9
+ bnez a4, __mulsf_return_x
+ bne a3, t0, __mulsf_return_x
+ slli a5, a1, 9
+ bnez a5, __mulsf_return_y
+ ret // return x
+
+__mulsf_y_nan_inf:
+ // We know that x is not zero, nan, nor inf. That just leaves normals.
+ // y is nan -> return y
+ // y is inf -> return inf * sgn(x) (since we already merged the signs)
+ slli a5, a1, 9
+ bnez a5, __mulsf_return_y
+ srai a0, a0, 31
+ packh a0, t0, a0
+ slli a0, a0, 23
+ ret
+
+
+// This is a hack to improve soft float performance for the routines we don't
+// implement (e.g. libm) in libraries built against a non-Zbb ISA dialect:
+float_section __clz2si
+.global __clz2si
+__clz2si:
+ clz a0, a0
+ ret
diff --git a/src/rp2_common/pico_float/include/pico/float.h b/src/rp2_common/pico_float/include/pico/float.h
index 70730279d..6cafc83e4 100644
--- a/src/rp2_common/pico_float/include/pico/float.h
+++ b/src/rp2_common/pico_float/include/pico/float.h
@@ -21,8 +21,8 @@ extern "C" {
*
* \brief Optimized single-precision floating point functions
*
-* (Replacement) optimized implementations are provided of the following compiler built-ins
-* and math library functions:
+* (Replacement) optimized implementations are provided for the following compiler built-ins
+* and math library functions on Arm:
*
* - __aeabi_fadd, __aeabi_fdiv, __aeabi_fmul, __aeabi_frsub, __aeabi_fsub, __aeabi_cfcmpeq, __aeabi_cfrcmple, __aeabi_cfcmple, __aeabi_fcmpeq, __aeabi_fcmplt, __aeabi_fcmple, __aeabi_fcmpge, __aeabi_fcmpgt, __aeabi_fcmpun, __aeabi_i2f, __aeabi_l2f, __aeabi_ui2f, __aeabi_ul2f, __aeabi_f2iz, __aeabi_f2lz, __aeabi_f2uiz, __aeabi_f2ulz, __aeabi_f2d, sqrtf, cosf, sinf, tanf, atan2f, expf, logf
* - ldexpf, copysignf, truncf, floorf, ceilf, roundf, asinf, acosf, atanf, sinhf, coshf, tanhf, asinhf, acoshf, atanhf, exp2f, log2f, exp10f, log10f, powf, hypotf, cbrtf, fmodf, dremf, remainderf, remquof, expm1f, log1pf, fmaf
@@ -34,11 +34,18 @@ extern "C" {
* - float2fix, float2ufix, float2fix64, float2ufix64, float2int, float2uint, float2int64, float2uint64, float2int_z, float2int64_z, float2uint_z, float2uint64_z
* - exp10f, sincosf, powintf
*
-* On RP2350 the following additional functions are available; the _fast methods are faster but do not round correctly
+* On RP2350 (Arm) the following additional functions are available; the _fast methods are faster but do not round correctly
*
* - float2fix64_z, fdiv_fast, fsqrt_fast,
+*
+* On RP2350 RISC-V, only a small number of compiler runtime functions are overridden with faster implementations:
+*
+* - __addsf3, __subsf3, __mulsf3
*/
+// None of these functions are available on RISC-V:
+#if !defined(__riscv) || PICO_COMBINED_DOCS
+
float int2float(int32_t f);
float uint2float(uint32_t f);
float int642float(int64_t f);
@@ -74,6 +81,8 @@ float fdiv_fast(float n, float d);
float fsqrt_fast(float f);
#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/rp2_common/pico_i2c_slave/i2c_slave.c b/src/rp2_common/pico_i2c_slave/i2c_slave.c
index 6dc4960c4..1ef24c829 100644
--- a/src/rp2_common/pico_i2c_slave/i2c_slave.c
+++ b/src/rp2_common/pico_i2c_slave/i2c_slave.c
@@ -62,8 +62,7 @@ void i2c_slave_init(i2c_inst_t *i2c, uint8_t address, i2c_slave_handler_t handle
slave->handler = handler;
// Note: The I2C slave does clock stretching implicitly after a RD_REQ, while the Tx FIFO is empty.
- // There is also an option to enable clock stretching while the Rx FIFO is full, but we leave it
- // disabled since the Rx FIFO should never fill up (unless slave->handler() is way too slow).
+ // Clock stretching while the Rx FIFO is full is also enabled by default.
i2c_set_slave_mode(i2c, true, address);
i2c_hw_t *hw = i2c_get_hw(i2c);
diff --git a/src/rp2_common/pico_lwip/BUILD.bazel b/src/rp2_common/pico_lwip/BUILD.bazel
index 5c98e5415..c98ff92a2 100644
--- a/src/rp2_common/pico_lwip/BUILD.bazel
+++ b/src/rp2_common/pico_lwip/BUILD.bazel
@@ -25,11 +25,13 @@ cc_library(
"//src/rp2_common/pico_async_context",
"//src/rp2_common/pico_rand",
],
+ alwayslink = True,
)
cc_library(
name = "pico_lwip_nosys",
srcs = ["lwip_nosys.c"],
+ includes = ["include"],
hdrs = ["include/pico/lwip_nosys.h"],
target_compatible_with = compatible_with_pico_w(),
deps = [
@@ -39,6 +41,7 @@ cc_library(
"//src/rp2_common/pico_async_context",
"//src/rp2_common/pico_rand",
],
+ alwayslink = True,
)
# Prefer these aliases to directly referencing @lwip, as it's possible that
diff --git a/src/rp2_common/pico_lwip/lwip.BUILD b/src/rp2_common/pico_lwip/lwip.BUILD
index 83e2be779..c94b881c5 100644
--- a/src/rp2_common/pico_lwip/lwip.BUILD
+++ b/src/rp2_common/pico_lwip/lwip.BUILD
@@ -1,31 +1,46 @@
-load("@pico-sdk//bazel:defs.bzl", "incompatible_with_config")
+load("@pico-sdk//bazel:defs.bzl", "incompatible_with_config", "compatible_with_config")
package(default_visibility = ["//visibility:public"])
+# Some of the LWIP sys_arch.h and the lwip headers depend circularly on one
+# another. Include them all in the same target.
+cc_library(
+ name = "pico_lwip_headers",
+ hdrs = glob(["**/*.h"]),
+ includes = [
+ "contrib/ports/freertos/include/arch",
+ "src/include",
+ ],
+ visibility = [
+ "@pico-sdk//src/rp2_common/pico_lwip:__pkg__",
+ ],
+ deps = [
+ "@pico-sdk//src/rp2_common/pico_lwip:pico_lwip_config",
+ ],
+)
+
cc_library(
name = "pico_lwip_core",
srcs = glob(["src/core/*.c"]),
- hdrs = glob(["**/*.h"]),
- includes = ["src/include"],
- target_compatible_with = incompatible_with_config(
- "@pico-sdk//bazel/constraint:pico_lwip_config_unset",
- ),
deps = [
+ ":pico_lwip_headers",
"@pico-sdk//bazel/config:PICO_LWIP_CONFIG",
- "@pico-sdk//src/rp2_common/pico_lwip:pico_lwip_config",
],
+ target_compatible_with = incompatible_with_config("@pico-sdk//bazel/constraint:pico_lwip_config_unset")
)
cc_library(
name = "pico_lwip_core4",
srcs = glob(["src/core/ipv4/*.c"]),
deps = [":pico_lwip_core"],
+ alwayslink = True,
)
cc_library(
name = "pico_lwip_core6",
srcs = glob(["src/core/ipv6/*.c"]),
deps = [":pico_lwip_core"],
+ alwayslink = True,
)
cc_library(
@@ -151,13 +166,13 @@ cc_library(
cc_library(
name = "pico_lwip_contrib_freertos",
- srcs = ["ports/freertos/sys_arch.c"],
- includes = ["ports/freertos/include"],
+ srcs = ["contrib/ports/freertos/sys_arch.c"],
+ includes = ["contrib/ports/freertos/include"],
target_compatible_with = incompatible_with_config(
"@pico-sdk//bazel/constraint:pico_freertos_unset",
),
deps = [
- ":pico_lwip_core",
- "//bazel/config:PICO_FREERTOS_LIB",
+ ":pico_lwip_headers",
+ "@pico-sdk//bazel/config:PICO_FREERTOS_LIB",
],
)
diff --git a/src/rp2_common/pico_lwip/tools/makefsdata.py b/src/rp2_common/pico_lwip/tools/makefsdata.py
index 0ef113dfc..88fca43a6 100755
--- a/src/rp2_common/pico_lwip/tools/makefsdata.py
+++ b/src/rp2_common/pico_lwip/tools/makefsdata.py
@@ -1,30 +1,8 @@
#!/usr/bin/env python3
import argparse
+import mimetypes
from pathlib import Path
-
-file_types = {
- "html": "text/html",
- "htm": "text/html",
- "shtml": "text/html",
- "shtm": "text/html",
- "ssi": "text/html",
- "gif": "image/gif",
- "png": "image/png",
- "jpg": "image/jpeg",
- "bmp": "image/bmp",
- "ico": "image/x-icon",
- "class": "application/octet-stream",
- "cls": "application/octet-stream",
- "js": "application/javascript",
- "ram": "application/javascript",
- "css": "text/css",
- "swf": "application/x-shockwave-flash",
- "xml": "text/xml",
- "xsl": "application/pdf",
- "pdf": "text/xml",
- "json": "application/json",
- "svg": "image/svg+xml"
-}
+import re
response_types = {
200: "HTTP/1.0 200 OK",
@@ -41,9 +19,9 @@ def process_file(input_dir, file):
results = []
# Check content type
- content_type = file_types[file.suffix[1:].lower()]
+ content_type, _ = mimetypes.guess_type(file)
if content_type is None:
- raise RuntimeError(f"Unsupported file type {file.suffix}")
+ content_type = "application/octet-stream"
# file name
data = f"/{file.relative_to(input_dir)}\x00"
@@ -103,8 +81,12 @@ def process_file_list(fd, input):
# make a variable name
var_name = str(file.relative_to(input_dir))
- var_name = var_name.replace(".", "_")
- var_name = var_name.replace("/", "_")
+ var_name = re.sub(r"\W+", "_", var_name, flags=re.ASCII)
+
+ # Add a suffix if the variable name is used already
+ if any(d["data_var"] == f"data_{var_name}" for d in data):
+ var_name += f"_{len(data)}"
+
data_var = f"data_{var_name}"
file_var = f"file_{var_name}"
@@ -121,7 +103,7 @@ def process_file_list(fd, input):
if byte_count % 16 == 0:
fd.write("\n")
if byte_count % 16 != 0:
- fd.write("\n")
+ fd.write("\n")
fd.write(f"}};\n\n")
# set the flags
@@ -165,6 +147,11 @@ def run_tool():
)
args = parser.parse_args()
print(args.input)
+
+ mimetypes.init()
+ for ext in [".shtml", ".shtm", ".ssi"]:
+ mimetypes.add_type("text/html", ext)
+
with open(args.output, "w") as fd:
process_file_list(fd, args.input)
diff --git a/src/rp2_common/pico_malloc/malloc.c b/src/rp2_common/pico_malloc/malloc.c
index ca5411fc3..9597b9801 100644
--- a/src/rp2_common/pico_malloc/malloc.c
+++ b/src/rp2_common/pico_malloc/malloc.c
@@ -24,6 +24,39 @@ extern void REAL_FUNC(free)(void *mem);
extern char __StackLimit; /* Set by linker. */
+#if !PICO_USE_MALLOC_MUTEX
+#define MALLOC_ENTER(outer) ((void)0);
+#define MALLOC_EXIT(outer) ((void)0);
+#elif !__PICOLIBC__
+#define MALLOC_ENTER(outer) mutex_enter_blocking(&malloc_mutex);
+#define MALLOC_EXIT(outer) mutex_exit(&malloc_mutex);
+#else
+static uint8_t mutex_exception_level_plus_one[NUM_CORES];
+// PICOLIBC implementations of calloc and realloc may call malloc and free,
+// so we need to cope with re-entrant calls. We don't want to use a recursive
+// mutex as that won't catch usage within an ISR; instead we record the exception
+// nesting as of acquiring the mutex
+#define MALLOC_ENTER(outer) \
+ uint exception = __get_current_exception(); \
+ uint core_num = get_core_num(); \
+ /* we skip the locking on outer == false if we are in the same irq nesting */ \
+ /* note: the `+ 1` is to distinguish no malloc nesting vs no-exception/irq level */ \
+ bool do_lock = outer || exception + 1 != mutex_exception_level_plus_one[core_num]; \
+ if (do_lock) { \
+ mutex_enter_blocking(&malloc_mutex); \
+ if (outer) mutex_exception_level_plus_one[core_num] = (uint8_t)(exception + 1); \
+ }
+
+#define MALLOC_EXIT(outer) \
+ if (outer) { \
+ mutex_exception_level_plus_one[core_num] = 0; \
+ } \
+ if (do_lock) { \
+ mutex_exit(&malloc_mutex); \
+ }
+
+#endif
+
static inline void check_alloc(__unused void *mem, __unused uint size) {
#if PICO_MALLOC_PANIC
if (!mem || (((char *)mem) + size) > &__StackLimit) {
@@ -33,13 +66,9 @@ static inline void check_alloc(__unused void *mem, __unused uint size) {
}
void *WRAPPER_FUNC(malloc)(size_t size) {
-#if PICO_USE_MALLOC_MUTEX
- mutex_enter_blocking(&malloc_mutex);
-#endif
+ MALLOC_ENTER(false)
void *rc = REAL_FUNC(malloc)(size);
-#if PICO_USE_MALLOC_MUTEX
- mutex_exit(&malloc_mutex);
-#endif
+ MALLOC_EXIT(false)
#if PICO_DEBUG_MALLOC
if (!rc) {
printf("malloc %d failed to allocate memory\n", (uint) size);
@@ -52,13 +81,9 @@ void *WRAPPER_FUNC(malloc)(size_t size) {
}
void *WRAPPER_FUNC(calloc)(size_t count, size_t size) {
-#if PICO_USE_MALLOC_MUTEX
- mutex_enter_blocking(&malloc_mutex);
-#endif
+ MALLOC_ENTER(true)
void *rc = REAL_FUNC(calloc)(count, size);
-#if PICO_USE_MALLOC_MUTEX
- mutex_exit(&malloc_mutex);
-#endif
+ MALLOC_EXIT(true)
#if PICO_DEBUG_MALLOC
if (!rc) {
printf("calloc %d failed to allocate memory\n", (uint) (count * size));
@@ -71,13 +96,9 @@ void *WRAPPER_FUNC(calloc)(size_t count, size_t size) {
}
void *WRAPPER_FUNC(realloc)(void *mem, size_t size) {
-#if PICO_USE_MALLOC_MUTEX
- mutex_enter_blocking(&malloc_mutex);
-#endif
+ MALLOC_ENTER(true)
void *rc = REAL_FUNC(realloc)(mem, size);
-#if PICO_USE_MALLOC_MUTEX
- mutex_exit(&malloc_mutex);
-#endif
+ MALLOC_EXIT(true)
#if PICO_DEBUG_MALLOC
if (!rc) {
printf("realloc %d failed to allocate memory\n", (uint) size);
@@ -90,11 +111,7 @@ void *WRAPPER_FUNC(realloc)(void *mem, size_t size) {
}
void WRAPPER_FUNC(free)(void *mem) {
-#if PICO_USE_MALLOC_MUTEX
- mutex_enter_blocking(&malloc_mutex);
-#endif
+ MALLOC_ENTER(false)
REAL_FUNC(free)(mem);
-#if PICO_USE_MALLOC_MUTEX
- mutex_exit(&malloc_mutex);
-#endif
+ MALLOC_EXIT(false)
}
diff --git a/src/rp2_common/pico_mem_ops/BUILD.bazel b/src/rp2_common/pico_mem_ops/BUILD.bazel
index 495347c26..df9128d7c 100644
--- a/src/rp2_common/pico_mem_ops/BUILD.bazel
+++ b/src/rp2_common/pico_mem_ops/BUILD.bazel
@@ -44,6 +44,7 @@ cc_library(
deps = [
"//src/rp2_common:pico_platform_internal",
"//src/rp2_common/pico_bootrom",
+ "//src/rp2_common/pico_runtime_init",
],
alwayslink = True, # Ensures the wrapped symbols are linked in.
)
diff --git a/src/rp2_common/pico_multicore/include/pico/multicore.h b/src/rp2_common/pico_multicore/include/pico/multicore.h
index a45f2a6c7..c452b9822 100644
--- a/src/rp2_common/pico_multicore/include/pico/multicore.h
+++ b/src/rp2_common/pico_multicore/include/pico/multicore.h
@@ -29,7 +29,7 @@ extern "C" {
* \include multicore.c
*/
-// PICO_CONFIG: PICO_CORE1_STACK_SIZE, Minimum amount of stack space reserved in the linker script for core 1, min=0x100, max=0x10000, default=PICO_STACK_SIZE (0x800), group=pico_multicore
+// PICO_CONFIG: PICO_CORE1_STACK_SIZE, Minimum amount of stack space reserved in the linker script for core 1 - if zero then no space is reserved and the user must provide their own stack, min=0, max=0x10000, default=PICO_STACK_SIZE (0x800), group=pico_multicore
#ifndef PICO_CORE1_STACK_SIZE
#ifdef PICO_STACK_SIZE
#define PICO_CORE1_STACK_SIZE PICO_STACK_SIZE
@@ -449,7 +449,7 @@ static inline uint multicore_doorbell_irq_num(uint doorbell_num) {
*/
void multicore_lockout_victim_init(void);
-/*! \brief Determine if \ref multicore_victim_init() has been called on the specified core.
+/*! \brief Determine if \ref multicore_lockout_victim_init() has been called on the specified core.
* \ingroup multicore_lockout
*
* \note this state persists even if the core is subsequently reset; therefore you are advised to
@@ -457,7 +457,7 @@ void multicore_lockout_victim_init(void);
* been initialized.
*
* \param core_num the core number (0 or 1)
- * \return true if \ref multicore_victim_init() has been called on the specified core, false otherwise.
+ * \return true if \ref multicore_lockout_victim_init() has been called on the specified core, false otherwise.
*/
bool multicore_lockout_victim_is_initialized(uint core_num);
diff --git a/src/rp2_common/pico_multicore/multicore.c b/src/rp2_common/pico_multicore/multicore.c
index 07afb3817..f5615c5b5 100644
--- a/src/rp2_common/pico_multicore/multicore.c
+++ b/src/rp2_common/pico_multicore/multicore.c
@@ -66,8 +66,10 @@ bool multicore_fifo_pop_timeout_us(uint64_t timeout_us, uint32_t *out) {
return true;
}
+#if PICO_CORE1_STACK_SIZE > 0
// Default stack for core1 ... if multicore_launch_core1 is not included then .stack1 section will be garbage collected
static uint32_t __attribute__((section(".stack1"))) core1_stack[PICO_CORE1_STACK_SIZE / sizeof(uint32_t)];
+#endif
static void __attribute__ ((naked)) core1_trampoline(void) {
#ifdef __riscv
@@ -153,11 +155,15 @@ void multicore_launch_core1_with_stack(void (*entry)(void), uint32_t *stack_bott
}
void multicore_launch_core1(void (*entry)(void)) {
+#if PICO_CORE1_STACK_SIZE > 0
extern uint32_t __StackOneBottom;
uint32_t *stack_limit = (uint32_t *) &__StackOneBottom;
// hack to reference core1_stack although that pointer is wrong.... core1_stack should always be <= stack_limit, if not boom!
uint32_t *stack = core1_stack <= stack_limit ? stack_limit : (uint32_t *) -1;
multicore_launch_core1_with_stack(entry, stack, sizeof(core1_stack));
+#else
+ panic("multicore_launch_core1() can't be used when PICO_CORE1_STACK_SIZE == 0");
+#endif
}
void multicore_launch_core1_raw(void (*entry)(void), uint32_t *sp, uint32_t vector_table) {
diff --git a/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h b/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h
index 10ea7abe0..8c459fcbf 100644
--- a/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h
+++ b/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h
@@ -152,10 +152,12 @@ extern "C" {
#define pico_default_asm(...) __asm (".syntax unified\n" __VA_ARGS__)
#define pico_default_asm_volatile(...) __asm volatile (".syntax unified\n" __VA_ARGS__)
#define pico_default_asm_goto(...) __asm goto (".syntax unified\n" __VA_ARGS__)
+#define pico_default_asm_volatile_goto(...) __asm volatile goto (".syntax unified\n" __VA_ARGS__)
#else
#define pico_default_asm(...) __asm (__VA_ARGS__)
#define pico_default_asm_volatile(...) __asm volatile (__VA_ARGS__)
#define pico_default_asm_goto(...) __asm goto (__VA_ARGS__)
+#define pico_default_asm_volatile_goto(...) __asm volatile goto (__VA_ARGS__)
#endif
/*! \brief Ensure that the compiler does not move memory access across this method call
diff --git a/src/rp2_common/pico_platform_panic/panic.c b/src/rp2_common/pico_platform_panic/panic.c
index 7d076da90..06c063d2a 100644
--- a/src/rp2_common/pico_platform_panic/panic.c
+++ b/src/rp2_common/pico_platform_panic/panic.c
@@ -8,7 +8,7 @@
#include
#include
#include
-#include "pico/platform/panic.h"
+#include "pico.h"
#if LIB_PICO_PRINTF_PICO
#include "pico/printf.h"
@@ -37,8 +37,8 @@ void __attribute__((naked, noreturn)) __printflike(1, 0) panic(__unused const ch
#if !PICO_PANIC_FUNCTION_EMPTY
"jal " __XSTRING(PICO_PANIC_FUNCTION) "\n"
#endif
- "ebreak\n"
- "1: j 1b\n"
+ "1: ebreak\n"
+ "j 1b\n"
#else
@@ -46,8 +46,8 @@ void __attribute__((naked, noreturn)) __printflike(1, 0) panic(__unused const ch
#if !PICO_PANIC_FUNCTION_EMPTY
"bl " __XSTRING(PICO_PANIC_FUNCTION) "\n"
#endif
- "bkpt #0\n"
- "1: b 1b\n" // loop for ever as we are no return
+ "1: bkpt #0\n"
+ "b 1b\n" // loop for ever as we are no return
#endif
:
diff --git a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h
index 752e752a9..e85700295 100644
--- a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h
+++ b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h
@@ -143,7 +143,7 @@
*
* For example a function called my_func taking an int parameter:
*
- * void __time_critical(my_func)(int some_arg) {
+ * void __time_critical_func(my_func)(int some_arg) {
*
* The function is placed in the `.time_critical.` linker section
*
diff --git a/src/rp2_common/pico_rand/include/pico/rand.h b/src/rp2_common/pico_rand/include/pico/rand.h
index f2953162e..b0a337f24 100644
--- a/src/rp2_common/pico_rand/include/pico/rand.h
+++ b/src/rp2_common/pico_rand/include/pico/rand.h
@@ -70,7 +70,7 @@ extern "C" {
#endif
#endif
-// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_TRNG, Enable/disable use of hardware TRNG as an entropy source, type=bool, default=1 if no hardware TRNG, group=pico_rand
+// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_TRNG, Enable/disable use of hardware TRNG as an entropy source, type=bool, default=1 if hardware TRNG is available, group=pico_rand
#ifndef PICO_RAND_ENTROPY_SRC_TRNG
#if HAS_RP2350_TRNG
#define PICO_RAND_ENTROPY_SRC_TRNG 1
@@ -108,9 +108,9 @@ extern "C" {
#define PICO_RAND_SEED_ENTROPY_SRC_TIME PICO_RAND_ENTROPY_SRC_TIME
#endif
-// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_BUF_PERF_COUNTER, Enable/disable use of a bus performance counter as an entropy source for the random seed, type=bool, default=PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER, group=pico_rand
-#ifndef PICO_RAND_SEED_ENTROPY_SRC_BUF_PERF_COUNTER
-#define PICO_RAND_SEED_ENTROPY_SRC_BUF_PERF_COUNTER PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER
+// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_BUS_PERF_COUNTER, Enable/disable use of a bus performance counter as an entropy source for the random seed, type=bool, default=PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER, group=pico_rand
+#ifndef PICO_RAND_SEED_ENTROPY_SRC_BUS_PERF_COUNTER
+#define PICO_RAND_SEED_ENTROPY_SRC_BUS_PERF_COUNTER PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER
#endif
// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_BOOT_RANDOM, Enable/disable use of the per boot random number as an entropy source for the random seed, type=bool, default=0 on RP2040 which has none, group=pico_rand
diff --git a/src/rp2_common/pico_rand/rand.c b/src/rp2_common/pico_rand/rand.c
index 5d07fef42..794c63e4c 100644
--- a/src/rp2_common/pico_rand/rand.c
+++ b/src/rp2_common/pico_rand/rand.c
@@ -297,8 +297,8 @@ static void initialise_rand(void) {
#if PICO_RAND_SEED_ENTROPY_SRC_BUS_PERF_COUNTER
#if !PICO_RAND_BUS_PERF_COUNTER_INDEX
int idx = -1;
- for(uint i = 0; i < count_of(bus_ctrl_hw->counter); i++) {
- if (bus_ctrl_hw->counter[i].sel == BUSCTRL_PERFSEL0_RESET) {
+ for(uint i = 0; i < count_of(busctrl_hw->counter); i++) {
+ if (busctrl_hw->counter[i].sel == BUSCTRL_PERFSEL0_RESET) {
idx = (int)i;
break;
}
@@ -308,7 +308,7 @@ static void initialise_rand(void) {
#else
bus_counter_idx = (uint8_t)PICO_RAND_BUS_PERF_COUNTER_INDEX;
#endif
- bus_ctrl_hw->counter[bus_counter_idx].sel = PICO_RAND_BUS_PERF_COUNTER_EVENT;
+ busctrl_hw->counter[bus_counter_idx].sel = PICO_RAND_BUS_PERF_COUNTER_EVENT;
#endif
(void) xoroshiro128ss(&local_rng_state);
rng_state = local_rng_state;
diff --git a/src/rp2_common/pico_runtime/CMakeLists.txt b/src/rp2_common/pico_runtime/CMakeLists.txt
index 3665cd805..da329e695 100644
--- a/src/rp2_common/pico_runtime/CMakeLists.txt
+++ b/src/rp2_common/pico_runtime/CMakeLists.txt
@@ -65,7 +65,17 @@ endif()
# FLOAT - support for single-precision floating point
# DOUBLE - support for double-precision floating point
# FPGA_CHECK - checks for FPGA which allows Raspberry Pi to run your binary on FPGA
+# PANIC - default panic impl which brings in stdio
+# AUTO_INIT_MUTEX - auto init mutexes; without this you get no printf mutex either -
function(pico_minimize_runtime TARGET)
+ set(ALL_ITEMS
+ DEFAULT_ALARM_POOL
+ PRINTF
+ FLOAT
+ DOUBLE
+ FPGA_CHECK
+ PANIC
+ AUTO_INIT_MUTEX)
cmake_parse_arguments(RUNTIME "" ""
"INCLUDE;EXCLUDE" ${ARGN} )
foreach (INCL_EXCL IN ITEMS INCLUDE EXCLUDE)
@@ -75,7 +85,13 @@ function(pico_minimize_runtime TARGET)
set(VAL 0)
endif()
foreach(VAR IN LISTS RUNTIME_${INCL_EXCL})
- set(RUNTIME_INCLUDE_${VAR} ${VAL})
+ if (VAR STREQUAL "ALL")
+ foreach(ITEM IN LISTS ALL_ITEMS)
+ set(RUNTIME_INCLUDE_${ITEM} ${VAL})
+ endforeach ()
+ else()
+ set(RUNTIME_INCLUDE_${VAR} ${VAL})
+ endif()
endforeach ()
endforeach ()
if (NOT RUNTIME_INCLUDE_DEFAULT_ALARM_POOL)
@@ -114,6 +130,17 @@ function(pico_minimize_runtime TARGET)
pico_set_printf_implementation(${TARGET} none)
endif()
+ if (NOT RUNTIME_INCLUDE_PANIC)
+ target_compile_definitions(${TARGET} PRIVATE
+ PICO_PANIC_FUNCTION= #the default uses puts
+ )
+ endif()
+ if (NOT RUNTIME_INCLUDE_AUTO_INIT_MUTEX)
+ target_compile_definitions(${TARGET} PRIVATE
+ PICO_RUNTIME_NO_INIT_MUTEX=1
+ PICO_STDOUT_MUTEX=0 # currently pulls in mutex code otherwise
+ )
+ endif()
if (NOT RUNTIME_INCLUDE_FPGA_CHECK)
target_compile_definitions(${TARGET} PRIVATE PICO_NO_FPGA_CHECK=1)
endif()
diff --git a/src/rp2_common/pico_runtime_init/CMakeLists.txt b/src/rp2_common/pico_runtime_init/CMakeLists.txt
index 4d43bc555..769e4aa11 100644
--- a/src/rp2_common/pico_runtime_init/CMakeLists.txt
+++ b/src/rp2_common/pico_runtime_init/CMakeLists.txt
@@ -15,3 +15,6 @@ pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE
if (TARGET hardware_clocks)
pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE hardware_clocks)
endif()
+
+# pico/runtime_init.h includes pico/runtime.h
+target_link_libraries(pico_runtime_init_headers INTERFACE pico_runtime_headers)
\ No newline at end of file
diff --git a/src/rp2_common/pico_standard_binary_info/standard_binary_info.c b/src/rp2_common/pico_standard_binary_info/standard_binary_info.c
index 2ebc33805..c950f8db1 100644
--- a/src/rp2_common/pico_standard_binary_info/standard_binary_info.c
+++ b/src/rp2_common/pico_standard_binary_info/standard_binary_info.c
@@ -7,7 +7,7 @@
#if !PICO_NO_BINARY_INFO && !PICO_NO_PROGRAM_INFO
#include "pico/binary_info.h"
-#if LIB_PICO_BOOT_STAGE2_HEADERS && !PICO_NO_FLASH
+#if LIB_BOOT_STAGE2_HEADERS && !PICO_NO_FLASH
#include "boot_stage2/config.h"
#endif
diff --git a/src/rp2_common/pico_stdio_rtt/SEGGER/RTT/SEGGER_RTT.c b/src/rp2_common/pico_stdio_rtt/SEGGER/RTT/SEGGER_RTT.c
index f35540417..c69fca7d0 100644
--- a/src/rp2_common/pico_stdio_rtt/SEGGER/RTT/SEGGER_RTT.c
+++ b/src/rp2_common/pico_stdio_rtt/SEGGER/RTT/SEGGER_RTT.c
@@ -78,6 +78,11 @@ Additional information:
#include // for memcpy
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#pragma GCC diagnostic ignored "-Wcast-align"
+#endif
+
/*********************************************************************
*
* Configuration, default values
diff --git a/src/rp2_common/pico_stdio_rtt/stdio_rtt.c b/src/rp2_common/pico_stdio_rtt/stdio_rtt.c
index 2dc75579a..2af1f7028 100644
--- a/src/rp2_common/pico_stdio_rtt/stdio_rtt.c
+++ b/src/rp2_common/pico_stdio_rtt/stdio_rtt.c
@@ -26,11 +26,11 @@ void stdio_rtt_deinit(void) {
}
static void stdio_rtt_out_chars(const char *buf, int length) {
- SEGGER_RTT_Write(0, buf, length);
+ SEGGER_RTT_Write(0, buf, (unsigned)length);
}
static int stdio_rtt_in_chars(char *buf, int length) {
- return SEGGER_RTT_Read(0, buf, length);
+ return (int)SEGGER_RTT_Read(0, buf, (unsigned)length);
}
stdio_driver_t stdio_rtt = {
diff --git a/src/rp2_common/pico_stdio_uart/stdio_uart.c b/src/rp2_common/pico_stdio_uart/stdio_uart.c
index 620e25d15..54cd86e01 100644
--- a/src/rp2_common/pico_stdio_uart/stdio_uart.c
+++ b/src/rp2_common/pico_stdio_uart/stdio_uart.c
@@ -172,6 +172,8 @@ static void on_uart_rx(void) {
static void stdio_uart_set_chars_available_callback(void (*fn)(void*), void *param) {
uint irq_num = UART_IRQ_NUM(uart_instance);
if (fn && !chars_available_callback) {
+ chars_available_callback = fn;
+ chars_available_param = param;
irq_set_exclusive_handler(irq_num, on_uart_rx);
irq_set_enabled(irq_num, true);
uart_set_irqs_enabled(uart_instance, true, false);
@@ -179,14 +181,14 @@ static void stdio_uart_set_chars_available_callback(void (*fn)(void*), void *par
uart_set_irqs_enabled(uart_instance, false, false);
irq_set_enabled(irq_num, false);
irq_remove_handler(irq_num, on_uart_rx);
+ chars_available_callback = NULL;
+ chars_available_param = NULL;
}
- chars_available_callback = fn;
- chars_available_param = param;
}
#endif
static void stdio_uart_out_flush(void) {
- uart_default_tx_wait_blocking();
+ uart_tx_wait_blocking(uart_instance);
}
stdio_driver_t stdio_uart = {
diff --git a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
index 47fcf6731..b572998d8 100644
--- a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
+++ b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
@@ -51,7 +51,7 @@
#endif
#endif
-// PICO_CONFIG: PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE, baud rate that if selected causes a reset into BOOTSEL mode (if PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE is set), default=1200, group=pico_stdio_usb
+// PICO_CONFIG: PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE, Baud rate that if selected causes a reset into BOOTSEL mode (if PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE is set), default=1200, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE
#define PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE 1200
#endif
@@ -71,7 +71,12 @@
#define PICO_STDIO_USB_DEINIT_DELAY_MS 110
#endif
-// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=29, group=pico_stdio_usb
+// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=47 on RP2350B, 29 otherwise, group=pico_stdio_usb
+
+// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW, Whether pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE) is active low, type=bool, default=0, group=pico_stdio_usb
+#ifndef PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED_ACTIVE_LOW
+#define PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED_ACTIVE_LOW 0
+#endif
// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED, Whether the pin specified by PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED is fixed or can be modified by picotool over the VENDOR USB interface, type=bool, default=0, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
diff --git a/src/rp2_common/pico_stdio_usb/reset_interface.c b/src/rp2_common/pico_stdio_usb/reset_interface.c
index 4d52689a1..26afa3de1 100644
--- a/src/rp2_common/pico_stdio_usb/reset_interface.c
+++ b/src/rp2_common/pico_stdio_usb/reset_interface.c
@@ -119,16 +119,19 @@ static bool resetd_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL
if (request->bRequest == RESET_REQUEST_BOOTSEL) {
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
- uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
+ int gpio = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
+ bool active_low = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW;
#else
- uint gpio_mask = 0u;
+ int gpio = -1;
+ bool active_low = false;
#endif
#if !PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
if (request->wValue & 0x100) {
- gpio_mask = 1u << (request->wValue >> 9u);
+ gpio = request->wValue >> 9u;
}
+ active_low = request->wValue & 0x200;
#endif
- reset_usb_boot(gpio_mask, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
+ rom_reset_usb_boot_extra(gpio, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK, active_low);
// does not return, otherwise we'd return true
}
#endif
@@ -173,11 +176,13 @@ usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
void tud_cdc_line_coding_cb(__unused uint8_t itf, cdc_line_coding_t const* p_line_coding) {
if (p_line_coding->bit_rate == PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE) {
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
- const uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
+ int gpio = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
+ bool active_low = PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED_ACTIVE_LOW;
#else
- const uint gpio_mask = 0u;
+ int gpio = -1;
+ bool active_low = false;
#endif
- reset_usb_boot(gpio_mask, PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
+ rom_reset_usb_boot_extra(gpio, PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK, active_low);
}
}
#endif
diff --git a/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c b/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c
index 7ecfdffe7..2f6e75877 100644
--- a/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c
+++ b/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c
@@ -92,7 +92,15 @@
static const tusb_desc_device_t usbd_desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
+// On Windows, if bcdUSB = 0x210 then a Microsoft OS 2.0 descriptor is required, else the device won't be detected
+// This is only needed for driverless access to the reset interface - the CDC interface doesn't require these descriptors
+// for driverless access, but will still not work if bcdUSB = 0x210 and no descriptor is provided. Therefore always
+// use bcdUSB = 0x200 if the Microsoft OS 2.0 descriptor isn't enabled
+#if PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE && PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR
.bcdUSB = 0x0210,
+#else
+ .bcdUSB = 0x0200,
+#endif
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
diff --git a/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h b/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h
index bb25cc040..59308b4b9 100644
--- a/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h
+++ b/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h
@@ -36,7 +36,28 @@ static inline alarm_pool_timer_t *ta_from_current_irq(uint *alarm_num) {
}
static inline void ta_set_timeout(alarm_pool_timer_t *timer, uint alarm_num, int64_t target) {
- timer_hw_from_timer(timer)->alarm[alarm_num] = (uint32_t) target;
+ // We never want to set the timeout to be later than our current one.
+ uint32_t current = timer_time_us_32(timer_hw_from_timer(timer));
+ uint32_t time_til_target = (uint32_t) target - current;
+ uint32_t time_til_alarm = timer_hw_from_timer(timer)->alarm[alarm_num] - current;
+ // Note: we are only dealing with the low 32 bits of the timer values,
+ // so there is some opportunity to make wrap-around errors.
+ //
+ // 1. If we just passed the alarm time, then time_til_alarm will be high, meaning we will
+ // likely do the update, but this is OK since the alarm will have just fired
+ // 2. If we just passed the target time, then time_til_target will be high, meaning we will
+ // likely not do the update, but this is OK since the caller who has the full 64 bits
+ // must check if the target time has passed when we return anyway to avoid races.
+ if (time_til_target < time_til_alarm) {
+ timer_hw_from_timer(timer)->alarm[alarm_num] = (uint32_t) target;
+ }
+}
+
+static inline bool ta_wakes_up_on_or_before(alarm_pool_timer_t *timer, uint alarm_num, int64_t target) {
+ uint32_t current = timer_time_us_32(timer_hw_from_timer(timer));
+ uint32_t time_til_target = (uint32_t) target - current;
+ uint32_t time_til_alarm = timer_hw_from_timer(timer)->alarm[alarm_num] - current;
+ return time_til_alarm <= time_til_target;
}
static inline uint64_t ta_time_us_64(alarm_pool_timer_t *timer) {
diff --git a/src/rp2_common/pico_unique_id/include/pico/unique_id.h b/src/rp2_common/pico_unique_id/include/pico/unique_id.h
index bf32a86eb..367d32bff 100644
--- a/src/rp2_common/pico_unique_id/include/pico/unique_id.h
+++ b/src/rp2_common/pico_unique_id/include/pico/unique_id.h
@@ -18,9 +18,10 @@ extern "C" {
*
* \brief Unique device ID access API
*
+ * \if rp2040_specific
* RP2040 does not have an on-board unique identifier (all instances of RP2040
* silicon are identical and have no persistent state). However, RP2040 boots
- * from serial NOR flash devices which have a 64-bit unique ID as a standard
+ * from serial NOR flash devices which have at least a 64-bit unique ID as a standard
* feature, and there is a 1:1 association between RP2040 and flash, so this
* is suitable for use as a unique identifier for an RP2040-based board.
*
@@ -31,6 +32,11 @@ extern "C" {
*
* This avoids some pitfalls of the hardware_flash API, which requires any
* flash-resident interrupt routines to be disabled when called into.
+ * \endif
+ *
+ * \if rp2350_specific
+ * On boards using RP2350, the unique identifier is read from OTP memory on boot.
+ * \endif
*/
#define PICO_UNIQUE_BOARD_ID_SIZE_BYTES 8
@@ -39,9 +45,18 @@ extern "C" {
* \brief Unique board identifier
* \ingroup pico_unique_id
*
- * This struct is suitable for holding the unique identifier of a NOR flash
- * device on an RP2040-based board. It contains an array of
- * PICO_UNIQUE_BOARD_ID_SIZE_BYTES identifier bytes.
+ * This structure contains an array of PICO_UNIQUE_BOARD_ID_SIZE_BYTES identifier bytes suitable for
+ * holding the unique identifier for the device.
+ *
+ * \if rp2040_specific
+ * On an RP2040-based board, the unique identifier is retrieved from the external NOR flash device at boot,
+ * or for PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
+ * \endif
+ *
+ * \if rp2350_specific
+ * On an RP2350-based board, the unique identifier is retrieved from OTP memory at boot.
+ * \endif
+ *
*/
typedef struct {
uint8_t id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES];
@@ -50,10 +65,16 @@ typedef struct {
/*! \brief Get unique ID
* \ingroup pico_unique_id
*
- * Get the unique 64-bit device identifier which was retrieved from the
- * external NOR flash device at boot.
+ * Get the unique 64-bit device identifier.
+ *
+ * \if rp2040_specific
+ * On an RP2040-based board, the unique identifier is retrieved from the external NOR flash device at boot,
+ * or for PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
+ * \endif
*
- * On PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
+ * \if rp2350_specific
+ * On an RP2350-based board, the unique identifier is retrieved from OTP memory at boot.
+ * \endif
*
* \param id_out a pointer to a pico_unique_board_id_t struct, to which the identifier will be written
*/
@@ -62,11 +83,16 @@ void pico_get_unique_board_id(pico_unique_board_id_t *id_out);
/*! \brief Get unique ID in string format
* \ingroup pico_unique_id
*
- * Get the unique 64-bit device identifier which was retrieved from the
- * external NOR flash device at boot, formatted as an ASCII hex string.
- * Will always 0-terminate.
+ * Get the unique 64-bit device identifier formatted as a 0-terminated ASCII hex string.
+ *
+ * \if rp2040_specific
+ * On an RP2040-based board, the unique identifier is retrieved from the external NOR flash device at boot,
+ * or for PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
+ * \endif
*
- * On PICO_NO_FLASH builds the unique identifier is set to all 0xEE.
+ * \if rp2350_specific
+ * On an RP2350-based board, the unique identifier is retrieved from OTP memory at boot.
+ * \endif
*
* \param id_out a pointer to a char buffer of size len, to which the identifier will be written
* \param len the size of id_out. For full serial, len >= 2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1
diff --git a/src/rp2_common/pico_unique_id/unique_id.c b/src/rp2_common/pico_unique_id/unique_id.c
index 5406f3691..c027bf27d 100644
--- a/src/rp2_common/pico_unique_id/unique_id.c
+++ b/src/rp2_common/pico_unique_id/unique_id.c
@@ -8,7 +8,7 @@
#include "pico/bootrom.h"
#include "pico/unique_id.h"
-static_assert(PICO_UNIQUE_BOARD_ID_SIZE_BYTES == FLASH_UNIQUE_ID_SIZE_BYTES, "Board ID size must match flash ID size");
+static_assert(PICO_UNIQUE_BOARD_ID_SIZE_BYTES <= FLASH_UNIQUE_ID_SIZE_BYTES, "Board ID size must at least be the size of flash ID");
static pico_unique_board_id_t retrieved_id;
@@ -20,8 +20,16 @@ static void __attribute__((constructor)) _retrieve_unique_id_on_boot(void) {
// debug, so just produce something well-defined and obviously wrong.
for (int i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; i++)
retrieved_id.id[i] = 0xee;
- #else
+ #elif (PICO_UNIQUE_BOARD_ID_SIZE_BYTES == FLASH_UNIQUE_ID_SIZE_BYTES)
flash_get_unique_id(retrieved_id.id);
+ #elif (PICO_UNIQUE_BOARD_ID_SIZE_BYTES < FLASH_UNIQUE_ID_SIZE_BYTES)
+ // The flash ID is >8 bytes (e.g. IS25LP016D) but we want to keep the
+ // pico unique board ID as 8 bytes, just use the last 8 bytes which are likely to change
+ uint8_t flash_id[FLASH_UNIQUE_ID_SIZE_BYTES];
+ flash_get_unique_id(flash_id);
+ memcpy(retrieved_id.id, flash_id + FLASH_UNIQUE_ID_SIZE_BYTES - PICO_UNIQUE_BOARD_ID_SIZE_BYTES, PICO_UNIQUE_BOARD_ID_SIZE_BYTES);
+ #else
+ #error unique board ID size is greater than flash unique ID size
#endif
#else
rom_get_sys_info_fn func = (rom_get_sys_info_fn) rom_func_lookup(ROM_FUNC_GET_SYS_INFO);
diff --git a/test/cmsis_test/cmsis_test.c b/test/cmsis_test/cmsis_test.c
index bb0bebda6..6e9fdf62c 100644
--- a/test/cmsis_test/cmsis_test.c
+++ b/test/cmsis_test/cmsis_test.c
@@ -5,23 +5,35 @@
#else
#include "RP2350.h"
#endif
-#include "pico/stdio.h"
+#include "pico/stdlib.h"
+#include "hardware/irq.h"
__STATIC_FORCEINLINE int some_function(int i) {
return __CLZ(i);
}
-static bool pendsv_called;
+static bool pendsv_called, irq_handler_called;
void PendSV_Handler(void) {
pendsv_called = true;
}
+void DMA_IRQ_0_Handler(void) {
+ irq_handler_called = true;
+ irq_clear(DMA_IRQ_0_IRQn);
+}
+
int main(void) {
stdio_init_all();
for(int i=0;i<10;i++) {
printf("%d %d\n", i, some_function(i));
}
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+ printf("PENDSV: ");
puts(pendsv_called ? "SUCCESS" : "FAILURE");
+ printf("DMA_IRQ_0: ");
+ irq_set_enabled(DMA_IRQ_0_IRQn, true);
+ irq_set_pending(DMA_IRQ_0_IRQn);
+ puts(irq_handler_called ? "SUCCESS" : "FAILURE");
+ return !(pendsv_called && irq_handler_called);
}
diff --git a/test/kitchen_sink/BUILD.bazel b/test/kitchen_sink/BUILD.bazel
index ec3ea9fcf..1bd595c3e 100644
--- a/test/kitchen_sink/BUILD.bazel
+++ b/test/kitchen_sink/BUILD.bazel
@@ -6,10 +6,6 @@ package(default_visibility = ["//visibility:public"])
cc_library(
name = "btstack_config",
hdrs = ["btstack_config.h"],
- defines = [
- "ENABLE_CLASSIC=1",
- "ENABLE_BLE=1",
- ],
includes = ["."],
)
@@ -60,6 +56,7 @@ cc_library(
"//src/rp2_common/hardware_uart",
"//src/rp2_common/hardware_vreg",
"//src/rp2_common/hardware_watchdog",
+ "//src/rp2_common/hardware_xip_cache",
"//src/rp2_common/hardware_xosc",
"//src/rp2_common/pico_aon_timer",
"//src/rp2_common/pico_bootrom",
@@ -112,6 +109,7 @@ cc_binary(
deps = [
":kitchen_sink_common",
"//src/rp2_common/pico_cyw43_arch:pico_cyw43_arch_lwip_poll",
+ "//src/rp2_common/pico_btstack:pico_btstack",
],
)
@@ -132,6 +130,8 @@ kitchen_sink_test_binary(
src = ":kitchen_sink_lwip_poll_actual",
bt_stack_config = ":btstack_config",
lwip_config = ":lwip_config",
+ enable_ble = True,
+ enable_bt_classic = True,
target_compatible_with = compatible_with_rp2(),
)
@@ -141,5 +141,7 @@ kitchen_sink_test_binary(
src = ":kitchen_sink_lwip_background_actual",
bt_stack_config = ":btstack_config",
lwip_config = ":lwip_config",
+ enable_ble = True,
+ enable_bt_classic = True,
target_compatible_with = compatible_with_rp2(),
)
diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt
index 5395129d6..afc77e553 100644
--- a/test/kitchen_sink/CMakeLists.txt
+++ b/test/kitchen_sink/CMakeLists.txt
@@ -24,6 +24,7 @@ set(KITCHEN_SINK_LIBS
hardware_uart
hardware_vreg
hardware_watchdog
+ hardware_xip_cache
hardware_xosc
pico_aon_timer
pico_bit_ops
@@ -179,7 +180,7 @@ if (TARGET pico_cyw43_arch)
target_link_libraries(kitchen_sink_lwip_poll
pico_btstack_ble pico_btstack_classic pico_btstack_cyw43)
endif()
- # for lwipopts.h
+ # for lwipopts.h and btstack_config.h.
target_include_directories(kitchen_sink_lwip_poll PRIVATE
${CMAKE_CURRENT_LIST_DIR})
diff --git a/test/pico_float_test/BUILD.bazel b/test/pico_float_test/BUILD.bazel
index ce35a9d74..1efdf724d 100644
--- a/test/pico_float_test/BUILD.bazel
+++ b/test/pico_float_test/BUILD.bazel
@@ -3,6 +3,29 @@ load("//bazel/util:transition.bzl", "pico_float_test_binary")
package(default_visibility = ["//visibility:public"])
+cc_binary(
+ name = "hazard3_test_gen",
+ srcs = ["hazard3_test_gen.c"],
+ target_compatible_with = ["//bazel/constraint:host"],
+)
+
+# TODO: Set up a transition to build this under RISC-V.
+cc_binary(
+ name = "pico_float_test_hazard3",
+ testonly = True,
+ srcs = [
+ "pico_float_test_hazard3.c",
+ "vectors/hazard3_addsf.inc",
+ "vectors/hazard3_mulsf.inc",
+ ],
+ includes = ["."],
+ target_compatible_with = compatible_with_rp2() + ["@platforms//cpu:riscv32"],
+ deps = [
+ "//src/rp2_common/pico_float",
+ "//src/rp2_common/pico_stdlib",
+ ],
+)
+
cc_binary(
name = "pico_float_test",
testonly = True,
diff --git a/test/pico_float_test/CMakeLists.txt b/test/pico_float_test/CMakeLists.txt
index e0e0a814a..971c2a6d7 100644
--- a/test/pico_float_test/CMakeLists.txt
+++ b/test/pico_float_test/CMakeLists.txt
@@ -1,7 +1,22 @@
PROJECT(pico_float_test)
-# todo revist this test for
-if (NOT PICO_RISCV)
+
+if (PICO_RISCV)
+
+ # Separate, simpler test: currently we only have a few single-precision
+ # routines for RISC-V soft float (and the other tests are a bit
+ # AEABI-dependent)
+ add_executable(pico_float_test
+ pico_float_test_hazard3.c
+ )
+ target_link_libraries(pico_float_test PRIVATE pico_float pico_stdlib)
+ target_include_directories(pico_float_test PRIVATE ${CMAKE_CURRENT_LIST_DIR})
+ pico_add_extra_outputs(pico_float_test)
+
+ # pico_enable_stdio_usb(pico_float_test 1)
+ # pico_enable_stdio_uart(pico_float_test 0)
+
+else ()
add_executable(pico_float_test
pico_float_test.c
llvm/call_apsr.S
@@ -64,4 +79,4 @@ if (NOT PICO_RISCV)
target_link_libraries(m33 pico_double pico_stdlib)
pico_add_extra_outputs(m33)
endif()
-endif()
\ No newline at end of file
+endif()
diff --git a/test/pico_float_test/hazard3_test_gen.c b/test/pico_float_test/hazard3_test_gen.c
new file mode 100644
index 000000000..0367513f3
--- /dev/null
+++ b/test/pico_float_test/hazard3_test_gen.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include
+#include
+#include
+#include
+
+// xoroshiro256++ pseudorandom number generator.
+// Adapted from: https://prng.di.unimi.it/xoshiro256plusplus.c
+// Original copyright notice:
+
+/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See . */
+
+/* This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
+ It has excellent (sub-ns) speed, a state (256 bits) that is large
+ enough for any parallel application, and it passes all tests we are
+ aware of.
+
+ For generating just floating-point numbers, xoshiro256+ is even faster.
+
+ The state must be seeded so that it is not everywhere zero. If you have
+ a 64-bit seed, we suggest to seed a splitmix64 generator and use its
+ output to fill s. */
+
+static inline uint64_t xr256_rotl(const uint64_t x, int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+uint64_t xr256_next(uint64_t s[4]) {
+ const uint64_t result = xr256_rotl(s[0] + s[3], 23) + s[0];
+
+ const uint64_t t = s[1] << 17;
+
+ s[2] ^= s[0];
+ s[3] ^= s[1];
+ s[1] ^= s[2];
+ s[0] ^= s[3];
+
+ s[2] ^= t;
+
+ s[3] = xr256_rotl(s[3], 45);
+
+ return result;
+}
+uint32_t bitcast_f2u(float x) {
+ // This is UB but then so is every C program
+ union {
+ float f;
+ uint32_t u;
+ } un;
+ un.f = x;
+ return un.u;
+}
+
+float bitcast_u2f(uint32_t x) {
+ union {
+ float f;
+ uint32_t u;
+ } un;
+ un.u = x;
+ return un.f;
+}
+
+bool is_nan_u(uint32_t x) {
+ return ((x >> 23) & 0xffu) == 0xffu && (x & ~(-1u << 23));
+}
+
+uint32_t flush_to_zero_u(uint32_t x) {
+ if (!(x & (0xffu << 23))) {
+ x &= -1u << 23;
+ }
+ return x;
+}
+
+uint32_t model_fadd(uint32_t x, uint32_t y) {
+ x = flush_to_zero_u(x);
+ y = flush_to_zero_u(y);
+ // Use local hardware implementation to perform calculation
+ uint32_t result = bitcast_f2u(bitcast_u2f(x) + bitcast_u2f(y));
+ // Use correct canonical generated nan
+ if (is_nan_u(result)) {
+ result = -1u;
+ }
+ result = flush_to_zero_u(result);
+ return result;
+}
+
+uint32_t model_fmul(uint32_t x, uint32_t y) {
+ x = flush_to_zero_u(x);
+ y = flush_to_zero_u(y);
+ // Use local hardware implementation to perform calculation
+ uint32_t result = bitcast_f2u(bitcast_u2f(x) * bitcast_u2f(y));
+ // Use correct canonical generated nan
+ if (is_nan_u(result)) {
+ result = -1u;
+ }
+ result = flush_to_zero_u(result);
+ return result;
+}
+
+int main() {
+ // SHA-256 of a rude word
+ uint64_t rand_state[4] = {
+ 0x5891b5b522d5df08u,
+ 0x6d0ff0b110fbd9d2u,
+ 0x1bb4fc7163af34d0u,
+ 0x8286a2e846f6be03u
+ };
+ for (int i = 0; i < 1000; ++i) {
+ uint32_t x, y;
+ x = xr256_next(rand_state) & 0xffffffffu;
+ y = xr256_next(rand_state) & 0xffffffffu;
+ // Map nan to +-inf (input nans should already be well-covered)
+ if (is_nan_u(x)) {
+ x &= -1u << 23;
+ }
+ if (is_nan_u(y)) {
+ y &= -1u << 23;
+ }
+#if 1
+ printf("{0x%08xu, 0x%08xu, 0x%08xu},\n", x, y, model_fadd(x, y));
+#else
+ printf("{0x%08xu, 0x%08xu, 0x%08xu},\n", x, y, model_fmul(x, y));
+#endif
+ }
+}
diff --git a/test/pico_float_test/pico_double_test.c b/test/pico_float_test/pico_double_test.c
index 530b3ff93..3b7a8ec29 100644
--- a/test/pico_float_test/pico_double_test.c
+++ b/test/pico_float_test/pico_double_test.c
@@ -17,6 +17,9 @@
#include
#include
#include "pico/stdlib.h"
+// Include sys/types.h before inttypes.h to work around issue with
+// certain versions of GCC and newlib which causes omission of PRIx64
+#include
#include "inttypes.h"
#define test_assert(x) ({ if (!(x)) { printf("Assertion failed: ");puts(#x);printf(" at " __FILE__ ":%d\n", __LINE__); exit(-1); } })
diff --git a/test/pico_float_test/pico_float_test.c b/test/pico_float_test/pico_float_test.c
index ca178474d..147fcc0e6 100644
--- a/test/pico_float_test/pico_float_test.c
+++ b/test/pico_float_test/pico_float_test.c
@@ -17,6 +17,9 @@
#include
#include
#include "pico/stdlib.h"
+// Include sys/types.h before inttypes.h to work around issue with
+// certain versions of GCC and newlib which causes omission of PRIx64
+#include
#include "inttypes.h"
#define test_assert(x) ({ if (!(x)) { printf("Assertion failed: ");puts(#x);printf(" at " __FILE__ ":%d\n", __LINE__); exit(-1); } })
diff --git a/test/pico_float_test/pico_float_test_hazard3.c b/test/pico_float_test/pico_float_test_hazard3.c
new file mode 100644
index 000000000..47da23b8d
--- /dev/null
+++ b/test/pico_float_test/pico_float_test_hazard3.c
@@ -0,0 +1,221 @@
+/**
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include
+#include "pico/stdlib.h"
+
+// This test covers the single-precision functions in:
+//
+// src/pico_float/float_hazard3_single.S
+//
+// It assumes the canonical generated-NaN value and NaN sign rules used by
+// those functions (which are unspecified by IEEE 754). It does not cover
+// libgcc/libm functions from outside of that source file.
+
+typedef struct {
+ uint32_t x;
+ uint32_t y;
+ uint32_t expect;
+} test_t;
+
+test_t add_directed_tests[] = {
+ // 1 + 1 = 2
+ {0x3f800000u, 0x3f800000u, 0x40000000u},
+ // 2 + 1 = 3
+ {0x40000000u, 0x3f800000u, 0x40400000u},
+ // 1 + 2 = 3
+ {0x3f800000u, 0x40000000u, 0x40400000u},
+ // 1 + -1 = +0 (exact cancellation)
+ {0x3f800000u, 0xbf800000u, 0x00000000u},
+ // -1 + 1 = +0 (exact cancellation)
+ {0xbf800000u, 0x3f800000u, 0x00000000u},
+ // 1 + <<1 ulp = 1
+ {0x3f800000u, 0x2f800000u, 0x3f800000u},
+ // <<1 ulp + 1 = 1
+ {0x2f800000u, 0x3f800000u, 0x3f800000u},
+ // -1 + 1.25 = 0.25
+ {0xbf800000u, 0x3fa00000u, 0x3e800000u},
+ // max normal + 0.5 ulp = +inf
+ {0x7f7fffffu, 0x73000000u, 0x7f800000u},
+ // max normal + max normal = +inf
+ {0x7f7fffffu, 0x7f7fffffu, 0x7f800000u},
+ // min normal - 0.5 ulp = -inf
+ {0xff7fffffu, 0xf3000000u, 0xff800000u},
+ // min normal + min_normal = -inf
+ {0xff7fffffu, 0xff7fffffu, 0xff800000u},
+ // max normal + 0.499... ulp = max normal
+ {0x7f7fffffu, 0x72ffffffu, 0x7f7fffffu},
+ // min normal - 0.499... ulp = min normal
+ {0xff7fffffu, 0xf2ffffffu, 0xff7fffffu},
+ // nan + 0 = same nan
+ {0xffff1234u, 0x00000000u, 0xffff1234u},
+ // 0 + nan = same nan
+ {0x00000000u, 0xffff1234u, 0xffff1234u},
+ // nan + 1 = same nan
+ {0xffff1234u, 0x3f800000u, 0xffff1234u},
+ // 1 + nan = same nan
+ {0x3f800000u, 0xffff1234u, 0xffff1234u},
+ // nan + inf = same nan
+ {0xffff1234u, 0x7f800000u, 0xffff1234u},
+ // inf + nan = same nan
+ {0x7f800000u, 0xffff1234u, 0xffff1234u},
+ // inf + inf = inf
+ {0x7f800000u, 0x7f800000u, 0x7f800000u},
+ // -inf + -inf = -inf
+ {0xff800000u, 0xff800000u, 0xff800000u},
+ // inf + -inf = nan (all-ones is our canonical cheap nan)
+ {0x7f800000u, 0xff800000u, 0xffffffffu},
+ // -inf + inf = nan
+ {0xff800000u, 0x7f800000u, 0xffffffffu},
+ // subnormal + subnormal = exactly 0
+ {0x007fffffu, 0x007fffffu, 0x00000000u},
+ // -subnormal + -subnormal = exactly -0
+ {0x807fffffu, 0x807fffffu, 0x80000000u},
+ // Even + 0.5 ulp: round down
+ {0x3f800002u, 0x33800000u, 0x3f800002u},
+ // Even - 0.5 ulp: round up
+ {0x3f800002u, 0xb3800000u, 0x3f800002u},
+ // Odd + 0.5 ulp: round up
+ {0x3f800001u, 0x33800000u, 0x3f800002u},
+ // Odd - 0.5 ulp: round down
+ {0x3f800001u, 0xb3800000u, 0x3f800000u},
+ // All-zeroes significand - 0.5 ulp: no rounding (exact)
+ {0x3f800000u, 0xb3800000u, 0x3f7fffffu},
+ // Very subnormal difference of normals: flushed to zero
+ {0x03800000u, 0x837fffffu, 0x00000000u},
+ // Barely subnormal difference of normals: also flushed (unflushed result is 2^(emin-1))
+ {0x03800000u, 0x837e0000u, 0x00000000u},
+};
+
+test_t mul_directed_tests[] = {
+ // -- directed tests --
+ // 1 * 1 = 1
+ {0x3f800000u, 0x3f800000u, 0x3f800000u},
+ // 1 * -1 = -1
+ {0x3f800000u, 0xbf800000u, 0xbf800000u},
+ // -1 * 1 = -1
+ {0xbf800000u, 0x3f800000u, 0xbf800000u},
+ // -1 * -1 = 1
+ {0xbf800000u, 0xbf800000u, 0x3f800000u},
+ // -0 * 0 = -0
+ {0x80000000u, 0x00000000u, 0x80000000u},
+ // 0 * -0 = - 0
+ {0x00000000u, 0x80000000u, 0x80000000u},
+ // 1 * 2 = 2
+ {0x3f800000u, 0x40000000u, 0x40000000u},
+ // 2 * 1 = 2
+ {0x40000000u, 0x3f800000u, 0x40000000u},
+ // inf * inf = inf
+ {0x7f800000u, 0x7f800000u, 0x7f800000u},
+ // inf * -inf = -inf
+ {0x7f800000u, 0xff800000u, 0xff800000u},
+ // inf * 0 = nan
+ {0x7f800000u, 0x00000000u, 0xffffffffu},
+ // 0 * inf = nan
+ {0x00000000u, 0x7f800000u, 0xffffffffu},
+ // 1 * -inf = -inf
+ {0x3f800000u, 0xff800000u, 0xff800000u},
+ // -inf * 1 = -inf
+ {0xff800000u, 0x3f800000u, 0xff800000u},
+ // -1 * inf = -inf
+ {0xbf800000u, 0x7f800000u, 0xff800000u},
+ // inf * -1 = -inf
+ {0x7f800000u, 0xbf800000u, 0xff800000u},
+ // 1 * nonzero subnormal = exactly 0
+ {0x3f800000u, 0x007fffffu, 0x00000000u},
+ // nonzero subnormal * -1 = exactly -0
+ {0x007fffffu, 0xbf800000u, 0x80000000u},
+ // nan * 0 = same nan
+ {0xffff1234u, 0x00000000u, 0xffff1234u},
+ // 0 * nan = same nan
+ {0x00000000u, 0xffff1234u, 0xffff1234u},
+ // nan * 1 = same nan
+ {0xffff1234u, 0x3f800000u, 0xffff1234u},
+ // 1 * nan = same nan
+ {0x3f800000u, 0xffff1234u, 0xffff1234u},
+ // nan * inf = same nan
+ {0xffff1234u, 0x7f800000u, 0xffff1234u},
+ // inf * nan = same nan
+ {0x7f800000u, 0xffff1234u, 0xffff1234u},
+ // (2 - 0.5 ulp) x (2 - 0.5 ulp) = 4 - 0.5 ulp
+ {0x3fffffffu, 0x3fffffffu, 0x407ffffeu},
+ // (2 - 0.5 ulp) x (1 + 1 ulp) = 2 exactly
+ {0xbfffffffu, 0x3f800001u, 0xc0000000u},
+ // 1.666... * 1.333.. = 2.222...
+ {0x3fd55555u, 0x3faaaaaau, 0x400e38e3u},
+ // 1.25 x 2^-63 x 1.25 x 2^-64 = 0
+ // (normal inputs with subnormal output, and we claim to be FTZ)
+ {0x20200000u, 0x1fa00000u, 0x00000000u},
+ // 1.333333 (rounded down) x 1.5 = 2 - 1 ulp
+ {0x3faaaaaau, 0x3fc00000u, 0x3fffffffu},
+ // 1.333333 (rounded down) x (1.5 + 1 ulp) = 2 exactly
+ {0x3faaaaaau, 0x3fc00001u, 0x40000000u},
+ // (1.333333 (rounded down) + 1 ulp) x 1.5 = 2 exactly
+ {0x3faaaaabu, 0x3fc00000u, 0x40000000u},
+ // (1.25 - 1 ulp) x (0.8 + 1 ulp) = 1 exactly (exponent increases after rounding)
+ {0x3f9fffffu, 0x3f4cccceu, 0x3f800000u},
+ // as above, but overflow on exponent increase -> +inf
+ {0x3f9fffffu, 0x7f4cccceu, 0x7f800000u},
+ // subtract 1 ulp from rhs -> largest normal
+ {0x3f9fffffu, 0x7f4ccccdu, 0x7f7fffffu},
+};
+
+#define N_RANDOM_TESTS 1000
+extern test_t add_random_tests[N_RANDOM_TESTS];
+extern test_t mul_random_tests[N_RANDOM_TESTS];
+
+uint32_t __addsf3(uint32_t x, uint32_t y);
+uint32_t __mulsf3(uint32_t x, uint32_t y);
+
+int run_tests(test_t *tests, int n_tests, const char *op_str, uint32_t (*func)(uint32_t, uint32_t)) {
+ int failed = 0;
+ for (int i = 0; i < n_tests; ++i) {
+ uint32_t actual = func(tests[i].x, tests[i].y);
+ if (tests[i].expect != actual) {
+ printf("%08x %s %08x -> %08x", tests[i].x, op_str, tests[i].y, tests[i].expect);
+ printf(" FAIL: got %08x\n", actual);
+ ++failed;
+ }
+ }
+ printf("Passed: %d / %d\n", n_tests - failed, n_tests);
+ return failed;
+}
+
+int main() {
+ stdio_init_all();
+ int failed = 0;
+ sleep_ms(3000);
+ printf("Testing: __addsf3 (directed tests)\n");
+ failed += run_tests(add_directed_tests, count_of(add_directed_tests), "+", __addsf3);
+ printf("Testing: __mulsf3 (directed tests)\n");
+ failed += run_tests(mul_directed_tests, count_of(mul_directed_tests), "*", __mulsf3);
+ if (failed) {
+ printf("Skipping random tests due to %d test failures\n", failed);
+ goto done;
+ }
+ printf("Testing: __addsf3 (random tests)\n");
+ failed += run_tests(add_random_tests, N_RANDOM_TESTS, "+", __addsf3);
+ printf("Testing: __mulsf3 (random tests)\n");
+ failed += run_tests(mul_random_tests, N_RANDOM_TESTS, "*", __mulsf3);
+
+ printf("%d tests failed.\n", failed);
+ if (failed == 0) {
+ printf("Well done, you can relax now\n");
+ }
+done:
+ while (true) {asm volatile ("wfi\n");} // keep USB stdout alive
+ return 0;
+}
+
+// Generated using the FPU on my machine (Zen 4) plus FTZ on inputs/outputs
+// See hazard3_test_gen.c
+test_t add_random_tests[N_RANDOM_TESTS] = {
+#include "vectors/hazard3_addsf.inc"
+};
+
+test_t mul_random_tests[N_RANDOM_TESTS] = {
+#include "vectors/hazard3_mulsf.inc"
+};
diff --git a/test/pico_float_test/vectors/hazard3_addsf.inc b/test/pico_float_test/vectors/hazard3_addsf.inc
new file mode 100644
index 000000000..1e651863d
--- /dev/null
+++ b/test/pico_float_test/vectors/hazard3_addsf.inc
@@ -0,0 +1,1000 @@
+{0xa8c36b34u, 0x420ac26bu, 0x420ac26bu},
+{0xd4cf10fbu, 0x692b079au, 0x692b079au},
+{0xece2254du, 0xf36c2cbbu, 0xf36c33ccu},
+{0x34f22bceu, 0x7c3b1110u, 0x7c3b1110u},
+{0x8b187e6fu, 0xa51e4bfcu, 0xa51e4bfcu},
+{0x0fe7c179u, 0xf0dcc0beu, 0xf0dcc0beu},
+{0x768e7ddbu, 0x2ccdc929u, 0x768e7ddbu},
+{0x06f19a7fu, 0x07562985u, 0x07a77b62u},
+{0xa20ff19cu, 0xa6a951a3u, 0xa6a9999cu},
+{0x64120a7fu, 0x935577e7u, 0x64120a7fu},
+{0x900ed7f5u, 0x970a63d2u, 0x970a660du},
+{0xec7a91c8u, 0x00eb6ee1u, 0xec7a91c8u},
+{0x87e4daa6u, 0xc88e8901u, 0xc88e8901u},
+{0xf005a09du, 0xcbf5a56eu, 0xf005a09du},
+{0x112e23edu, 0x7be85175u, 0x7be85175u},
+{0x04f3339au, 0x3a78a8b1u, 0x3a78a8b1u},
+{0x0a3232f6u, 0xea32f851u, 0xea32f851u},
+{0xc98f9ea4u, 0xebf90ffbu, 0xebf90ffbu},
+{0xed8bd406u, 0x9502d86fu, 0xed8bd406u},
+{0x0ab44d09u, 0x940a9806u, 0x940a97efu},
+{0x53117f9fu, 0x53160ff3u, 0x5393c7c9u},
+{0x455cf9c4u, 0x091efc06u, 0x455cf9c4u},
+{0x9d04dffdu, 0x9edd80dfu, 0x9eee1cdfu},
+{0x90c2fa22u, 0x93b5cbacu, 0x93b8d795u},
+{0x3c093424u, 0x9c303566u, 0x3c093424u},
+{0xd24a550du, 0x407dcb3au, 0xd24a550du},
+{0xd2d5e0d8u, 0xca9b966au, 0xd2d5e174u},
+{0x72d858b8u, 0x4c1960eeu, 0x72d858b8u},
+{0x9a63d2c3u, 0xcb110969u, 0xcb110969u},
+{0xe45bfe13u, 0xfc3a9028u, 0xfc3a9028u},
+{0x57c64c27u, 0x5273314du, 0x57c66a8du},
+{0xa72f1718u, 0xc739117fu, 0xc739117fu},
+{0x90cdb148u, 0x2eabbf2eu, 0x2eabbf2eu},
+{0xb2b429d1u, 0x821353fdu, 0xb2b429d1u},
+{0xe202a662u, 0x62997577u, 0x6230448cu},
+{0xc60df1c6u, 0xed07b0f2u, 0xed07b0f2u},
+{0x471b9543u, 0x08082cefu, 0x471b9543u},
+{0x6455a3a1u, 0x45398a87u, 0x6455a3a1u},
+{0x29186441u, 0x62e3a555u, 0x62e3a555u},
+{0xe2c75f26u, 0x3599d32eu, 0xe2c75f26u},
+{0xf4bebe05u, 0xcb41a1a2u, 0xf4bebe05u},
+{0xc76ef852u, 0xd3598bb3u, 0xd3598bb4u},
+{0xc05c09e9u, 0x632ab30au, 0x632ab30au},
+{0xc2cf6165u, 0xfb0298c1u, 0xfb0298c1u},
+{0xdef32a63u, 0x8cf06bb1u, 0xdef32a63u},
+{0x6309cbb1u, 0xe35417fau, 0xe2949892u},
+{0x6d985555u, 0xf5175c80u, 0xf5175b4fu},
+{0xe9ff5030u, 0x6756d007u, 0xe9f899b0u},
+{0xa422e9a4u, 0xaac9bd17u, 0xaac9c22eu},
+{0x9f73dbe2u, 0xd5eff474u, 0xd5eff474u},
+{0x79b20fb8u, 0x47ac4525u, 0x79b20fb8u},
+{0x79657aebu, 0x1f618dc6u, 0x79657aebu},
+{0x5634c9a9u, 0x7be5371fu, 0x7be5371fu},
+{0xfdee3dc7u, 0x2e8e3e83u, 0xfdee3dc7u},
+{0x5a1ac874u, 0x13a1d923u, 0x5a1ac874u},
+{0x16b2d812u, 0xdd6d97ebu, 0xdd6d97ebu},
+{0x9ed19073u, 0x76251aa0u, 0x76251aa0u},
+{0x8da689c9u, 0x879b3f68u, 0x8da6937du},
+{0x286d1e51u, 0xfa5a7310u, 0xfa5a7310u},
+{0x056fd052u, 0x69d08989u, 0x69d08989u},
+{0xc817e61au, 0xc10685d9u, 0xc817e834u},
+{0xf9f6dd82u, 0x2a8478c0u, 0xf9f6dd82u},
+{0xf8dda0c4u, 0x2199c318u, 0xf8dda0c4u},
+{0x12be4771u, 0x93f7babeu, 0x93c828e2u},
+{0x87025952u, 0x7343aac6u, 0x7343aac6u},
+{0xad1d7a9bu, 0x7719cbf0u, 0x7719cbf0u},
+{0x54f5897bu, 0xb35f912eu, 0x54f5897bu},
+{0xf7e27b8fu, 0x70e0c4d7u, 0xf7e2780cu},
+{0x3d616a83u, 0xde7053eeu, 0xde7053eeu},
+{0x587d62edu, 0x049ebffbu, 0x587d62edu},
+{0x69ca38e3u, 0xa5c40679u, 0x69ca38e3u},
+{0x4c69735du, 0x523e190du, 0x523e27a4u},
+{0x63cd7aafu, 0x5efe2fe2u, 0x63cdba3bu},
+{0xd58fc30fu, 0xbdb01383u, 0xd58fc30fu},
+{0x16c7da66u, 0xee4c113eu, 0xee4c113eu},
+{0x5e04dbefu, 0x6dba378fu, 0x6dba378fu},
+{0xc446094fu, 0x9ec4300du, 0xc446094fu},
+{0xb45c7b1au, 0xbf9add0au, 0xbf9add0cu},
+{0x527a78acu, 0xa9ec462fu, 0x527a78acu},
+{0x9c859f1bu, 0x326a03a0u, 0x326a03a0u},
+{0x1ecdbc33u, 0xd4deca58u, 0xd4deca58u},
+{0xc491b64du, 0xe4999dfbu, 0xe4999dfbu},
+{0xea0d3b6du, 0x152c5167u, 0xea0d3b6du},
+{0x6800639du, 0x9a7c0071u, 0x6800639du},
+{0x4e5ab470u, 0x2524d77fu, 0x4e5ab470u},
+{0xde821748u, 0x9a314294u, 0xde821748u},
+{0xd7d90f91u, 0x9dfddaf5u, 0xd7d90f91u},
+{0x9a6e422fu, 0x11ea2cb0u, 0x9a6e41bau},
+{0xfa305a4du, 0x9f8ef775u, 0xfa305a4du},
+{0x7f800000u, 0x7ecf8ff4u, 0x7f800000u},
+{0xf7dae75au, 0x5b89388du, 0xf7dae75au},
+{0x8ad2ce1bu, 0xfd15989eu, 0xfd15989eu},
+{0x8549054fu, 0x0715aa2fu, 0x070919dau},
+{0x08df8085u, 0x3290efa7u, 0x3290efa7u},
+{0xf9b05b50u, 0x45e3e467u, 0xf9b05b50u},
+{0xd618c7aau, 0x1a21e62eu, 0xd618c7aau},
+{0xb3e9d07du, 0x448a2a2au, 0x448a2a2au},
+{0x0817d23eu, 0x0e17145bu, 0x0e171dd8u},
+{0xf04863cfu, 0xb0dd3e34u, 0xf04863cfu},
+{0x85638413u, 0x621f50a4u, 0x621f50a4u},
+{0x9a347165u, 0x1ecf7f68u, 0x1ecf252fu},
+{0xaf5ada17u, 0x7552e217u, 0x7552e217u},
+{0x21533a8eu, 0x8b0c2dccu, 0x21533a8eu},
+{0x18191651u, 0x6543b033u, 0x6543b033u},
+{0xc571ce01u, 0x53ea5287u, 0x53ea5287u},
+{0xbb28e01cu, 0x473d6337u, 0x473d6336u},
+{0xc8a926bau, 0x4e62c441u, 0x4e62af1cu},
+{0x86e68079u, 0xac7bd4d7u, 0xac7bd4d7u},
+{0x47c8f07cu, 0x3cc49f10u, 0x47c8f07fu},
+{0x51021af4u, 0x5f10c5b9u, 0x5f10c5b9u},
+{0xe4632eb6u, 0x6b2d427fu, 0x6b2d3ef2u},
+{0xedc45634u, 0x5cdda5e6u, 0xedc45634u},
+{0xb84b8830u, 0x5b9592bcu, 0x5b9592bcu},
+{0x8938d3f5u, 0xca4e93a0u, 0xca4e93a0u},
+{0x12719b2bu, 0x9c8e3423u, 0x9c8e341bu},
+{0xb8bd54e7u, 0x7a605659u, 0x7a605659u},
+{0x06ec8b7eu, 0x5db893fbu, 0x5db893fbu},
+{0xf4ebdffeu, 0x40b27058u, 0xf4ebdffeu},
+{0x23350fafu, 0x98728c6au, 0x23350fabu},
+{0x706b89e4u, 0xddcfca5fu, 0x706b89e4u},
+{0xa5d39e54u, 0xdfd530dcu, 0xdfd530dcu},
+{0x1be13ddeu, 0xe872fa18u, 0xe872fa18u},
+{0x77f1e5ccu, 0xcd2aace2u, 0x77f1e5ccu},
+{0x2ba740c0u, 0xcd4f0df0u, 0xcd4f0df0u},
+{0xec00d47au, 0xe8afd26au, 0xec02341fu},
+{0xc4edce44u, 0xfc8ee969u, 0xfc8ee969u},
+{0x9be790c0u, 0x9e5342e7u, 0x9e5a7f6du},
+{0x9c3e0849u, 0xc0407137u, 0xc0407137u},
+{0x74d95ccau, 0x499ec4d6u, 0x74d95ccau},
+{0x4252fc0au, 0xaec0d9ceu, 0x4252fc0au},
+{0x5e1ebb93u, 0xa8859ebdu, 0x5e1ebb93u},
+{0x0d0175c2u, 0x7c008c86u, 0x7c008c86u},
+{0x250b16bdu, 0x407f9125u, 0x407f9125u},
+{0x296e1ea4u, 0x87e1aae2u, 0x296e1ea4u},
+{0xf4aba78eu, 0x2ef60552u, 0xf4aba78eu},
+{0x1d82e696u, 0xdeafc368u, 0xdeafc368u},
+{0xfcad4897u, 0x6b27581fu, 0xfcad4897u},
+{0xb5298a46u, 0x2935b912u, 0xb5298a45u},
+{0x53cc8f9eu, 0xeb6bcce3u, 0xeb6bcce3u},
+{0x554e7b84u, 0x53d11e1eu, 0x55689f48u},
+{0x22688415u, 0x70958cc3u, 0x70958cc3u},
+{0x152672b2u, 0x9a60547fu, 0x9a602ae2u},
+{0x14deaf74u, 0x50655ae7u, 0x50655ae7u},
+{0x4bbb9cf8u, 0xebebf934u, 0xebebf934u},
+{0x164083e6u, 0x4b5d0277u, 0x4b5d0277u},
+{0x1fd0f48bu, 0x92716a0bu, 0x1fd0f48bu},
+{0xd57bc2cdu, 0x7a392010u, 0x7a392010u},
+{0xfe8230beu, 0x3b624f0au, 0xfe8230beu},
+{0x8bce666bu, 0x1324deadu, 0x1324dd10u},
+{0x58961825u, 0x74813fddu, 0x74813fddu},
+{0x9463214bu, 0x3b2f08e5u, 0x3b2f08e5u},
+{0xe701da5fu, 0x8e7b3a11u, 0xe701da5fu},
+{0x0350403eu, 0xf613e135u, 0xf613e135u},
+{0x3b3e2a49u, 0xc31f1bcdu, 0xc31f1b0fu},
+{0xa73d56afu, 0x5ed1c217u, 0x5ed1c217u},
+{0xf9ef302cu, 0x3cea9b94u, 0xf9ef302cu},
+{0x7698bdb0u, 0x4f66c1e6u, 0x7698bdb0u},
+{0xd4ec1ba4u, 0xacc6705au, 0xd4ec1ba4u},
+{0x90e88632u, 0x07c44193u, 0x90e88601u},
+{0x6010566eu, 0x91ac29ffu, 0x6010566eu},
+{0xfa3447b4u, 0xbc8fd826u, 0xfa3447b4u},
+{0xcd4db5c2u, 0xe98c545du, 0xe98c545du},
+{0x77f16de5u, 0xd4ec082eu, 0x77f16de5u},
+{0x541fb093u, 0xfb6de113u, 0xfb6de113u},
+{0x56c1453fu, 0xe86d86ffu, 0xe86d86ffu},
+{0xd81da361u, 0x792a4904u, 0x792a4904u},
+{0x664cd3b5u, 0xc4e298f4u, 0x664cd3b5u},
+{0xc0f9fcceu, 0xcae84da2u, 0xcae84db2u},
+{0xce9ee780u, 0x8d978179u, 0xce9ee780u},
+{0x0e9ce349u, 0x792a101du, 0x792a101du},
+{0x86e2f8beu, 0xcc52355bu, 0xcc52355bu},
+{0x04cf751fu, 0xe5db081eu, 0xe5db081eu},
+{0xf3ef93bcu, 0x422c4ea0u, 0xf3ef93bcu},
+{0x264db607u, 0xd39183beu, 0xd39183beu},
+{0xd6bc3563u, 0x6a6190ccu, 0x6a6190ccu},
+{0xb636fc08u, 0x7eb3e8feu, 0x7eb3e8feu},
+{0xa197dfa7u, 0xaedfa4b6u, 0xaedfa4b6u},
+{0x073b76f1u, 0xeebcaef0u, 0xeebcaef0u},
+{0xe5ee7e35u, 0x1bc60178u, 0xe5ee7e35u},
+{0x1c2744a1u, 0x630a7678u, 0x630a7678u},
+{0x0c497b83u, 0x918c5692u, 0x918c3d63u},
+{0x2a171d73u, 0xc9a434bfu, 0xc9a434bfu},
+{0x823d1dcdu, 0x45f1b213u, 0x45f1b213u},
+{0xc0506450u, 0x4623ebf1u, 0x4623deebu},
+{0x9ae3c913u, 0x91050c92u, 0x9ae3c924u},
+{0xff0ed2e2u, 0x517fcb19u, 0xff0ed2e2u},
+{0xc473b53bu, 0x78092ec6u, 0x78092ec6u},
+{0x82032198u, 0xfb4cf76eu, 0xfb4cf76eu},
+{0x35980202u, 0xced3eeeeu, 0xced3eeeeu},
+{0xe7cedb64u, 0x296fd530u, 0xe7cedb64u},
+{0x277ff958u, 0xe8d7f50eu, 0xe8d7f50eu},
+{0x2cad366bu, 0x9cfbfeb0u, 0x2cad366bu},
+{0x629f942au, 0x3ae81beeu, 0x629f942au},
+{0xa12cd2dcu, 0xfa8343ccu, 0xfa8343ccu},
+{0x5be17669u, 0x4e60602fu, 0x5be17669u},
+{0x08524ce5u, 0xe5e1179fu, 0xe5e1179fu},
+{0xb537d098u, 0x6a53b86au, 0x6a53b86au},
+{0x7f800000u, 0x1e181546u, 0x7f800000u},
+{0x84079f3au, 0x9862840fu, 0x9862840fu},
+{0x45e156b9u, 0x6d717dfdu, 0x6d717dfdu},
+{0x7a106dedu, 0xdd9c293fu, 0x7a106dedu},
+{0x715c13b5u, 0x069f52a6u, 0x715c13b5u},
+{0xfb3b0be7u, 0x96115bd2u, 0xfb3b0be7u},
+{0x653c8abfu, 0x5792ec21u, 0x653c8abfu},
+{0xd63ad2cfu, 0xbdcd9fc8u, 0xd63ad2cfu},
+{0x76494ff6u, 0xf168db59u, 0x764915bfu},
+{0xd750f478u, 0x93df6f29u, 0xd750f478u},
+{0x52591a58u, 0x62ce57f9u, 0x62ce57f9u},
+{0x59702e0cu, 0xac4d4be9u, 0x59702e0cu},
+{0x191b4f82u, 0x9c120c0fu, 0x9c0f9ed1u},
+{0x7571977du, 0x4868cd7au, 0x7571977du},
+{0xe323810du, 0xfb7823ecu, 0xfb7823ecu},
+{0xd8a31d0bu, 0xb1bf5ae8u, 0xd8a31d0bu},
+{0x9bbe493au, 0x9b621004u, 0x9c17a89eu},
+{0x0c424697u, 0x65cdc27fu, 0x65cdc27fu},
+{0x7f800000u, 0x42683410u, 0x7f800000u},
+{0xab28f27fu, 0x59f8206du, 0x59f8206du},
+{0x6564bca0u, 0x9b1ff586u, 0x6564bca0u},
+{0xdec04178u, 0x5ed95714u, 0x5d48ace0u},
+{0x448371b4u, 0x5e3e357fu, 0x5e3e357fu},
+{0xa5f210b1u, 0xf94c0e02u, 0xf94c0e02u},
+{0x24a6378eu, 0x44147833u, 0x44147833u},
+{0xb8c6ff13u, 0x1841bfe0u, 0xb8c6ff13u},
+{0x69bb56dbu, 0x04da540au, 0x69bb56dbu},
+{0x5a32d3c0u, 0x5085d6e0u, 0x5a32d3d1u},
+{0x86071b75u, 0xbd8a8247u, 0xbd8a8247u},
+{0x5b0fde08u, 0x95f8f8afu, 0x5b0fde08u},
+{0x1512023au, 0xc1c42a8eu, 0xc1c42a8eu},
+{0xa4acb190u, 0xbb6ea9deu, 0xbb6ea9deu},
+{0x18e7c2deu, 0xe277f7c4u, 0xe277f7c4u},
+{0xb1f9e28cu, 0x10fbeff2u, 0xb1f9e28cu},
+{0x7924eadeu, 0xbf64d412u, 0x7924eadeu},
+{0x789ef535u, 0x38f4a07eu, 0x789ef535u},
+{0x021e8172u, 0xb9e650fau, 0xb9e650fau},
+{0xd8118d29u, 0xd11d6aafu, 0xd8118f9fu},
+{0xbdf63515u, 0xce2dab29u, 0xce2dab29u},
+{0x5f8251f4u, 0x7e179812u, 0x7e179812u},
+{0xfbba6262u, 0x86b8f500u, 0xfbba6262u},
+{0x93daea6du, 0x0879f2bdu, 0x93daea6bu},
+{0xa747d748u, 0x3ef33374u, 0x3ef33374u},
+{0x44788a48u, 0xcf7689cfu, 0xcf7689cbu},
+{0xe102ff64u, 0xb1004639u, 0xe102ff64u},
+{0xb7c45bfbu, 0x6913675bu, 0x6913675bu},
+{0x7c7f098du, 0xfb75dedbu, 0x7c4191d6u},
+{0x8c9c1595u, 0xc2472a61u, 0xc2472a61u},
+{0xb5385374u, 0x1ed8a0a7u, 0xb5385374u},
+{0xddc4042cu, 0x3fc480cbu, 0xddc4042cu},
+{0x302472b2u, 0x5e5ab2c1u, 0x5e5ab2c1u},
+{0xe385760au, 0x5ec80bf3u, 0xe3854407u},
+{0xa47e90d8u, 0x49275c5du, 0x49275c5du},
+{0x0fa782dcu, 0xc80110b6u, 0xc80110b6u},
+{0xf541129bu, 0xed5cdcddu, 0xf5411378u},
+{0xbc8b5485u, 0x747c6604u, 0x747c6604u},
+{0x771a0bdbu, 0x75e87b47u, 0x77371b44u},
+{0x3cec3190u, 0xe16d9aceu, 0xe16d9aceu},
+{0x1b12dd4au, 0x006edd76u, 0x1b12dd4au},
+{0x352d8890u, 0xca2a465du, 0xca2a465du},
+{0xd6b158e9u, 0x56874a5au, 0xd5a83a3cu},
+{0x3e768f34u, 0x4bd0e6d8u, 0x4bd0e6d8u},
+{0xace8138au, 0x7323f795u, 0x7323f795u},
+{0x412bbacdu, 0xac93b408u, 0x412bbacdu},
+{0xf50b7df4u, 0xeafe09a3u, 0xf50b7dfcu},
+{0x1ca1a9eeu, 0xcf5fb2f1u, 0xcf5fb2f1u},
+{0x503dfd5au, 0xa4754cecu, 0x503dfd5au},
+{0x0d8c13d9u, 0xe58a2542u, 0xe58a2542u},
+{0xaaa3bafeu, 0x611228b6u, 0x611228b6u},
+{0x1dd6ef19u, 0xae41e166u, 0xae41e166u},
+{0x7960b488u, 0xc272dc21u, 0x7960b488u},
+{0xc0624f3du, 0x85dda8cfu, 0xc0624f3du},
+{0xbf08d4dfu, 0x6f988295u, 0x6f988295u},
+{0x55d5eccdu, 0xfd108bedu, 0xfd108bedu},
+{0xaf756370u, 0x0da455dau, 0xaf756370u},
+{0xadcb53f4u, 0x368d92f5u, 0x368d92c2u},
+{0x17c23c65u, 0x19e687f3u, 0x19f2abb9u},
+{0xfc56299cu, 0x109f5deeu, 0xfc56299cu},
+{0xb7283035u, 0x71112332u, 0x71112332u},
+{0xbe76e6aau, 0x0439471bu, 0xbe76e6aau},
+{0xa074b2deu, 0x7f5f1209u, 0x7f5f1209u},
+{0xa6567493u, 0x79b164cfu, 0x79b164cfu},
+{0xb182b0c1u, 0x6ddfa43au, 0x6ddfa43au},
+{0x7bf2caa1u, 0x41edd18du, 0x7bf2caa1u},
+{0x0f0cdbd1u, 0x00b49f90u, 0x0f0cdbd1u},
+{0xc3c51598u, 0x9c9a4211u, 0xc3c51598u},
+{0xa2062836u, 0x3bfa8e6fu, 0x3bfa8e6fu},
+{0x0c688981u, 0xb6e94aafu, 0xb6e94aafu},
+{0x356120c8u, 0x2f2dd448u, 0x35612ba5u},
+{0xcbcc6a19u, 0xe0ea5993u, 0xe0ea5993u},
+{0x36fa2bdcu, 0xf67a5019u, 0xf67a5019u},
+{0x6d8a2515u, 0xe1169809u, 0x6d8a2515u},
+{0xb9eb555fu, 0x4c9f1a43u, 0x4c9f1a43u},
+{0x980be345u, 0x64a8aa95u, 0x64a8aa95u},
+{0x7dd9393fu, 0x4f630044u, 0x7dd9393fu},
+{0x337bb1b8u, 0xf10d1928u, 0xf10d1928u},
+{0xc0911657u, 0xa33438e5u, 0xc0911657u},
+{0xa9bb3347u, 0xa89148a7u, 0xa9df8571u},
+{0x7012388eu, 0x46718003u, 0x7012388eu},
+{0x2212b6f6u, 0x07b8720bu, 0x2212b6f6u},
+{0x9e30abe1u, 0xf36ff0d6u, 0xf36ff0d6u},
+{0xf6fcba04u, 0x012a4b6au, 0xf6fcba04u},
+{0x34002f95u, 0x1f38e6a8u, 0x34002f95u},
+{0xa6167252u, 0x7df22c86u, 0x7df22c86u},
+{0x780dcfe5u, 0x56aaa18du, 0x780dcfe5u},
+{0xf2c6de70u, 0x1fc965a9u, 0xf2c6de70u},
+{0x2a512a46u, 0x958615aau, 0x2a512a46u},
+{0x36d7d88du, 0x02540181u, 0x36d7d88du},
+{0xda0c6e88u, 0x1082c61cu, 0xda0c6e88u},
+{0x3e3d540au, 0x303538f1u, 0x3e3d540au},
+{0xa049ce49u, 0x362c9ba2u, 0x362c9ba2u},
+{0xe78410d2u, 0xf2398d43u, 0xf2398d47u},
+{0xf1c83119u, 0x6a5280b4u, 0xf1c82f74u},
+{0x5fed8b8au, 0xcde19518u, 0x5fed8b8au},
+{0x33917d1au, 0xa64d153fu, 0x33917d1au},
+{0x41bd6eb2u, 0x13f591d5u, 0x41bd6eb2u},
+{0xf293c81au, 0xf5aa50b0u, 0xf5ac9fd0u},
+{0x33052b7au, 0x440e4c2eu, 0x440e4c2eu},
+{0x23acc2cau, 0x375254b1u, 0x375254b1u},
+{0x6bd2777du, 0xeba980f8u, 0x6aa3da14u},
+{0x58564c9eu, 0x9a0e77c2u, 0x58564c9eu},
+{0xea41abd4u, 0x9cb52c7cu, 0xea41abd4u},
+{0x1eb7498cu, 0x9d07a9c7u, 0x1ea65453u},
+{0x0c041629u, 0x07c78a87u, 0x0c0479eeu},
+{0x0fca17dfu, 0x0b3ebf44u, 0x0fca773fu},
+{0x7aac6ddfu, 0xab105af2u, 0x7aac6ddfu},
+{0xa5060a6fu, 0x4ff5594eu, 0x4ff5594eu},
+{0xe874d8e9u, 0xa08cf274u, 0xe874d8e9u},
+{0x1ebbc68fu, 0xe14d3d20u, 0xe14d3d20u},
+{0x0a734f2fu, 0xd7682c59u, 0xd7682c59u},
+{0xd87a3ddbu, 0x16427d5au, 0xd87a3ddbu},
+{0xaf429e20u, 0x1634d2d5u, 0xaf429e20u},
+{0xfacd5e20u, 0x3bb70e12u, 0xfacd5e20u},
+{0xe994c008u, 0x1ffa86f8u, 0xe994c008u},
+{0xf198e8afu, 0x16fbfa58u, 0xf198e8afu},
+{0xe276ba65u, 0x92077527u, 0xe276ba65u},
+{0xbbdb544fu, 0x8529df27u, 0xbbdb544fu},
+{0x96322539u, 0x1954f1b0u, 0x1952291bu},
+{0x084ef10cu, 0x977dc0acu, 0x977dc0acu},
+{0xba0eea2fu, 0x9007ef12u, 0xba0eea2fu},
+{0x14bd40d9u, 0x66f6f196u, 0x66f6f196u},
+{0x4cd666bfu, 0x70a378e5u, 0x70a378e5u},
+{0x310c7409u, 0xf0facbc7u, 0xf0facbc7u},
+{0xe9a825edu, 0x4b9962f0u, 0xe9a825edu},
+{0x2a1c8022u, 0xa44aa6c1u, 0x2a1c7378u},
+{0xee7026c4u, 0xaab1b351u, 0xee7026c4u},
+{0xc649373eu, 0x37c9312au, 0xc649373eu},
+{0x2e582ab5u, 0x55ea2172u, 0x55ea2172u},
+{0x6816315eu, 0x3b9f3990u, 0x6816315eu},
+{0x702d7689u, 0x9829509fu, 0x702d7689u},
+{0x9e4c45aau, 0xe7ed4d17u, 0xe7ed4d17u},
+{0x635e1164u, 0x8c05f15eu, 0x635e1164u},
+{0x1265ee75u, 0xe48855c3u, 0xe48855c3u},
+{0xec2594f2u, 0x560f551eu, 0xec2594f2u},
+{0xac92e4f0u, 0xe579984au, 0xe579984au},
+{0x530db66cu, 0x1a8cf528u, 0x530db66cu},
+{0xbb886033u, 0xc2f78e20u, 0xc2f79042u},
+{0x5cafd674u, 0xe77c9f5bu, 0xe77c9f56u},
+{0xe753a713u, 0x4055dbc2u, 0xe753a713u},
+{0xb024aae8u, 0x60a3e7acu, 0x60a3e7acu},
+{0xd39b11a2u, 0x4f04aeb8u, 0xd39acf4bu},
+{0x5a19fc67u, 0xa53f10bcu, 0x5a19fc67u},
+{0xe5d49601u, 0xe9638523u, 0xe9652e4fu},
+{0x5d012455u, 0xd4db479au, 0x5d0123e7u},
+{0xbcef46f5u, 0xf1027763u, 0xf1027763u},
+{0xdd276b4fu, 0xc454d96cu, 0xdd276b4fu},
+{0x79e9a56bu, 0xf16e7839u, 0x79e9a4f4u},
+{0xc9052bbeu, 0x721c661fu, 0x721c661fu},
+{0x93260226u, 0x72ace9c8u, 0x72ace9c8u},
+{0x52d03c64u, 0x1208d792u, 0x52d03c64u},
+{0xe85a4dfeu, 0xd2924c9cu, 0xe85a4dfeu},
+{0xb3d5f200u, 0xd76e0b9bu, 0xd76e0b9bu},
+{0x65e5e39cu, 0x64cf4d3au, 0x660cdb75u},
+{0x28531053u, 0xbcb4a275u, 0xbcb4a275u},
+{0x21741210u, 0xc3241e74u, 0xc3241e74u},
+{0x4f87cbceu, 0xea71d988u, 0xea71d988u},
+{0x6224d352u, 0x8a47e325u, 0x6224d352u},
+{0x92f2c7fdu, 0x4a685e4du, 0x4a685e4du},
+{0x41b80d2bu, 0xa5db46bau, 0x41b80d2bu},
+{0x3b1a60e4u, 0x2e0b5601u, 0x3b1a60e4u},
+{0x996d731du, 0x639a8f42u, 0x639a8f42u},
+{0xf56d492eu, 0x5401ada1u, 0xf56d492eu},
+{0x1aaa1839u, 0x0dff892fu, 0x1aaa1839u},
+{0xea1d082bu, 0x36a16841u, 0xea1d082bu},
+{0x85aad29eu, 0x2f2914efu, 0x2f2914efu},
+{0xd42faa5fu, 0x6e3dd7fdu, 0x6e3dd7fdu},
+{0xa758d276u, 0x867aed1du, 0xa758d276u},
+{0xfd74de7bu, 0x369936d1u, 0xfd74de7bu},
+{0x822562a5u, 0x2806f8edu, 0x2806f8edu},
+{0x82ee1c6du, 0xdf817b5au, 0xdf817b5au},
+{0xdf51878du, 0xf1a93b59u, 0xf1a93b59u},
+{0xe95f499au, 0xaa92bf54u, 0xe95f499au},
+{0x595664eeu, 0xecc9389au, 0xecc9389au},
+{0x21ce5121u, 0xc499637bu, 0xc499637bu},
+{0x7d32eb15u, 0xb7a6d323u, 0x7d32eb15u},
+{0xa8cc4fedu, 0x554c1689u, 0x554c1689u},
+{0x98f28b4du, 0x3749b173u, 0x3749b173u},
+{0x9f8d7cd8u, 0x1d4b5eedu, 0x9f8721e1u},
+{0x46d628cfu, 0xf01abb5fu, 0xf01abb5fu},
+{0x879c02b2u, 0x4f1f5702u, 0x4f1f5702u},
+{0x495519abu, 0xa44eaeaeu, 0x495519abu},
+{0xbb6dd030u, 0x39b950ebu, 0xbb56a613u},
+{0x0d970075u, 0xe4c5a03au, 0xe4c5a03au},
+{0x7f731ba9u, 0x8bc6d6abu, 0x7f731ba9u},
+{0x1b11d520u, 0x40153ee1u, 0x40153ee1u},
+{0x1d8ab3b5u, 0x8a93ab32u, 0x1d8ab3b5u},
+{0xbed2a503u, 0xbfc48856u, 0xbff93197u},
+{0x6bb0242cu, 0x3af28fcau, 0x6bb0242cu},
+{0x2802d990u, 0xed1bbf90u, 0xed1bbf90u},
+{0x2e4b9bfau, 0x83fd3fbbu, 0x2e4b9bfau},
+{0xb4d22465u, 0x638754e9u, 0x638754e9u},
+{0x9aabc0a0u, 0x2109ee9eu, 0x2109e940u},
+{0x9f780664u, 0x9999c4a0u, 0x9f78199du},
+{0x31e671a8u, 0x3b9f803fu, 0x3b9f804du},
+{0xd3fd5754u, 0xd7b5439fu, 0xd7b640f6u},
+{0x93cc8660u, 0x3838c3a3u, 0x3838c3a3u},
+{0x8d7f6cfdu, 0xa17a2728u, 0xa17a2728u},
+{0x03b222f7u, 0xee8f7acfu, 0xee8f7acfu},
+{0xd96e532cu, 0x3690c62eu, 0xd96e532cu},
+{0xfbebba7cu, 0x3904c068u, 0xfbebba7cu},
+{0x3282ed92u, 0x2c2c8ef6u, 0x3282f2f6u},
+{0x2dab85e3u, 0x94e6d20eu, 0x2dab85e3u},
+{0xe8d32a7cu, 0x8256ca01u, 0xe8d32a7cu},
+{0x7889cf38u, 0xb5d224e0u, 0x7889cf38u},
+{0x0a636b5au, 0xec449d6du, 0xec449d6du},
+{0xaa864868u, 0xdbbaf35cu, 0xdbbaf35cu},
+{0xdc1d82a7u, 0xc7a718adu, 0xdc1d82a7u},
+{0x610affb1u, 0xe6a819c9u, 0xe6a80869u},
+{0x00bf372cu, 0x3dffe5b7u, 0x3dffe5b7u},
+{0x592d2cf2u, 0xa14b29c1u, 0x592d2cf2u},
+{0xe9e84611u, 0x45464a0cu, 0xe9e84611u},
+{0x45ab0c9bu, 0x008a0e28u, 0x45ab0c9bu},
+{0xae8501f8u, 0xd439b925u, 0xd439b925u},
+{0x92052ad0u, 0x35b22420u, 0x35b22420u},
+{0x4c2a5c49u, 0xc0e0b4cfu, 0x4c2a5c47u},
+{0xf224cc4eu, 0xe7be3f12u, 0xf224cc54u},
+{0x8c023902u, 0xda882ec9u, 0xda882ec9u},
+{0xcb311bebu, 0xcdb382e9u, 0xcdb90bc8u},
+{0xf955196eu, 0xbd4323deu, 0xf955196eu},
+{0x231bcb4eu, 0x7aa7a686u, 0x7aa7a686u},
+{0x5535c750u, 0x9e8b62b6u, 0x5535c750u},
+{0x1f28e619u, 0x3cd57406u, 0x3cd57406u},
+{0xc9b949deu, 0xb6fba018u, 0xc9b949deu},
+{0x09324eebu, 0x9a02c096u, 0x9a02c096u},
+{0x48e2c7feu, 0x1d3fe94eu, 0x48e2c7feu},
+{0x959a8ad4u, 0x884398d1u, 0x959a8ad4u},
+{0xc48b168du, 0x41570025u, 0xc489688du},
+{0xe840a92eu, 0x61cc7839u, 0xe840a2cau},
+{0x8e8381c6u, 0x99fbbb84u, 0x99fbbb86u},
+{0x2d4c9e48u, 0x1c851831u, 0x2d4c9e48u},
+{0x5f6646efu, 0xfec39eceu, 0xfec39eceu},
+{0xa387fddcu, 0x7a777ce0u, 0x7a777ce0u},
+{0x5da27df5u, 0x6b535404u, 0x6b535404u},
+{0xb006758eu, 0x7e6fefa3u, 0x7e6fefa3u},
+{0xb61d0982u, 0x0a52dae3u, 0xb61d0982u},
+{0x4b030676u, 0xc293e88fu, 0x4b03062cu},
+{0x17f6e095u, 0x2371352eu, 0x23713530u},
+{0x9f001e39u, 0xd784ae11u, 0xd784ae11u},
+{0xdd19e57eu, 0xbd305decu, 0xdd19e57eu},
+{0xc44d8484u, 0x6815117cu, 0x6815117cu},
+{0xf7957209u, 0x56afdde8u, 0xf7957209u},
+{0x4eb667d5u, 0x7ecbdc8eu, 0x7ecbdc8eu},
+{0xf35f4aecu, 0xae5e2b7eu, 0xf35f4aecu},
+{0x0b87b91fu, 0x22eacbf2u, 0x22eacbf2u},
+{0x553a2192u, 0x42eb13a2u, 0x553a2192u},
+{0x7cd2c724u, 0x3223fc12u, 0x7cd2c724u},
+{0xdb8e90a8u, 0xa7320869u, 0xdb8e90a8u},
+{0xf2ced7edu, 0xe76503c5u, 0xf2ced7efu},
+{0x28121aa0u, 0x807f59bcu, 0x28121aa0u},
+{0xc53d5941u, 0xd5e068bcu, 0xd5e068bcu},
+{0xff5558cdu, 0x6a243f83u, 0xff5558cdu},
+{0x71eb7177u, 0xf511b6f7u, 0xf50fe014u},
+{0x57d032b0u, 0x86ba91b5u, 0x57d032b0u},
+{0x7ce7fb2du, 0xa50c93e7u, 0x7ce7fb2du},
+{0x76e3acfbu, 0x4f7fa720u, 0x76e3acfbu},
+{0xc1d44b81u, 0xd1999596u, 0xd1999596u},
+{0x8e235a21u, 0xa6340b42u, 0xa6340b42u},
+{0x2a468744u, 0x581936cbu, 0x581936cbu},
+{0x42b348bcu, 0x666ac0d1u, 0x666ac0d1u},
+{0xf1d0d1dfu, 0xb56fedebu, 0xf1d0d1dfu},
+{0x46e3ee25u, 0x9d4a5000u, 0x46e3ee25u},
+{0x972f07aeu, 0x2db73d40u, 0x2db73d40u},
+{0x8c8ce88fu, 0x5cc175f9u, 0x5cc175f9u},
+{0xd4d33b08u, 0x028dc458u, 0xd4d33b08u},
+{0xae0fdb42u, 0x0b464db2u, 0xae0fdb42u},
+{0x9572f7b3u, 0xd892a113u, 0xd892a113u},
+{0x800f9576u, 0xfa8a438cu, 0xfa8a438cu},
+{0x37d39980u, 0x4cbde11eu, 0x4cbde11eu},
+{0x864e456fu, 0x588b9a67u, 0x588b9a67u},
+{0x09a55166u, 0xaae72998u, 0xaae72998u},
+{0x84fd542bu, 0x4feebd32u, 0x4feebd32u},
+{0x01d74270u, 0xb10165ecu, 0xb10165ecu},
+{0xb40eb722u, 0x0ec24b47u, 0xb40eb722u},
+{0x13246f90u, 0xba136117u, 0xba136117u},
+{0xff800000u, 0xa2ab84a3u, 0xff800000u},
+{0x5c842547u, 0x4981fe49u, 0x5c842547u},
+{0x76348f2cu, 0xcd7c07b3u, 0x76348f2cu},
+{0x1a446617u, 0x1556a3f8u, 0x1a449bc0u},
+{0xe60b31e5u, 0x1110c2a1u, 0xe60b31e5u},
+{0x42146406u, 0x37318767u, 0x42146409u},
+{0x5dc1d325u, 0x7579f997u, 0x7579f997u},
+{0xe6128c06u, 0x21219ac3u, 0xe6128c06u},
+{0x751154d4u, 0xe50d185eu, 0x751154d4u},
+{0x44b81d18u, 0x01fb4454u, 0x44b81d18u},
+{0xdb9c8d09u, 0x70d86877u, 0x70d86877u},
+{0xf8c6a031u, 0xa2ced56fu, 0xf8c6a031u},
+{0x32f5676au, 0xccd79bafu, 0xccd79bafu},
+{0xe3a28f65u, 0x3d0e65eeu, 0xe3a28f65u},
+{0x3faf074fu, 0x8b303b21u, 0x3faf074fu},
+{0xcce17c98u, 0x7e91c8e6u, 0x7e91c8e6u},
+{0x87a3750au, 0xd4afc420u, 0xd4afc420u},
+{0x0413b0cfu, 0x35baebe3u, 0x35baebe3u},
+{0xbb8d67eeu, 0xb1631569u, 0xbb8d67f5u},
+{0xd499c2c7u, 0x99990b0fu, 0xd499c2c7u},
+{0x0e366bb4u, 0x5bb5b406u, 0x5bb5b406u},
+{0x5bda0354u, 0xd50f86deu, 0x5bd9fed8u},
+{0x1dc6379au, 0x5eec61a7u, 0x5eec61a7u},
+{0x664065b3u, 0xcb642471u, 0x664065b3u},
+{0x94407d5cu, 0x167f0832u, 0x1673005cu},
+{0xb9b261d5u, 0xdd7ab004u, 0xdd7ab004u},
+{0x81a83ea9u, 0x87eb3556u, 0x87eb3fdau},
+{0x5987fb79u, 0x62e53844u, 0x62e53866u},
+{0x75662e31u, 0xa826c751u, 0x75662e31u},
+{0x408e0b25u, 0xa598ae8fu, 0x408e0b25u},
+{0x0820f517u, 0x26625bb2u, 0x26625bb2u},
+{0xe4554210u, 0xdde98d7du, 0xe455495cu},
+{0x95bd8c34u, 0xee722ce0u, 0xee722ce0u},
+{0x152f59d6u, 0x6b0c28ceu, 0x6b0c28ceu},
+{0x3c0bd9c3u, 0x6ed2df23u, 0x6ed2df23u},
+{0xa1b704d0u, 0x9ccb0449u, 0xa1b73791u},
+{0x29167178u, 0xf49bf8deu, 0xf49bf8deu},
+{0xbb6d3bbeu, 0x6b102eeeu, 0x6b102eeeu},
+{0x00de5449u, 0xf998fad5u, 0xf998fad5u},
+{0xbe51bc07u, 0x9f8851c5u, 0xbe51bc07u},
+{0x95d0f9f5u, 0x7d6b2ca4u, 0x7d6b2ca4u},
+{0xa5e2fd6du, 0xd759095au, 0xd759095au},
+{0x1092ce37u, 0x39334f75u, 0x39334f75u},
+{0xdae685aau, 0x948babdau, 0xdae685aau},
+{0x42393b0bu, 0xbf5788c2u, 0x4235dce8u},
+{0x43a39805u, 0x10fa441eu, 0x43a39805u},
+{0xa7929290u, 0xe4f8cf24u, 0xe4f8cf24u},
+{0xf63b7eabu, 0x525ac506u, 0xf63b7eabu},
+{0x1fa92001u, 0x9fb5ef4eu, 0x9dccf4d0u},
+{0xf8d2e0deu, 0xa0a9dad0u, 0xf8d2e0deu},
+{0x9304e87du, 0xeec4ab17u, 0xeec4ab17u},
+{0x0fc2e09bu, 0xe8e216dau, 0xe8e216dau},
+{0xa13c38ecu, 0xc3313b9cu, 0xc3313b9cu},
+{0x5ac82ca3u, 0x48a80f0au, 0x5ac82ca3u},
+{0x7a44192bu, 0x95cb0c3fu, 0x7a44192bu},
+{0x70942ae3u, 0xc8d144a1u, 0x70942ae3u},
+{0xf1ea09f0u, 0x632d86d7u, 0xf1ea09f0u},
+{0x4800da20u, 0xdd62d41du, 0xdd62d41du},
+{0x0d785aa6u, 0x2bdecf50u, 0x2bdecf50u},
+{0x38cb93c1u, 0xf05423c0u, 0xf05423c0u},
+{0x52cf9c2au, 0x75da4526u, 0x75da4526u},
+{0x2766413du, 0x80d9ca05u, 0x2766413du},
+{0xd7e1d37au, 0xf2eb3c19u, 0xf2eb3c19u},
+{0x51b65b44u, 0xc7d418e8u, 0x51b65b37u},
+{0xa4f884e5u, 0x59f9195du, 0x59f9195du},
+{0xe3779018u, 0xd6ad0352u, 0xe3779018u},
+{0x56b90433u, 0x6375eb0du, 0x6375eb0du},
+{0x40b035f5u, 0x367b31fdu, 0x40b035fdu},
+{0x8bfa4eccu, 0x31b8c7a4u, 0x31b8c7a4u},
+{0xfcc7acf9u, 0xfd19cda3u, 0xfd7da420u},
+{0x7b9ba076u, 0x1d2960d3u, 0x7b9ba076u},
+{0x13627eb2u, 0x7f586416u, 0x7f586416u},
+{0x92db39b6u, 0x3c0a9780u, 0x3c0a9780u},
+{0x7980ad43u, 0x99927d5eu, 0x7980ad43u},
+{0x4d32b075u, 0x7f766c1eu, 0x7f766c1eu},
+{0xcd3cafdeu, 0x6f0a66c6u, 0x6f0a66c6u},
+{0xc835a4d7u, 0x6602f533u, 0x6602f533u},
+{0x379ea377u, 0x6ef8e1c9u, 0x6ef8e1c9u},
+{0x7b33bc2bu, 0x09edacb5u, 0x7b33bc2bu},
+{0xd8dfaacfu, 0x16bcf3afu, 0xd8dfaacfu},
+{0xbb21f15cu, 0xbd6ad2e1u, 0xbd74f1f7u},
+{0x2099c0feu, 0x82517200u, 0x2099c0feu},
+{0xa404d4edu, 0xff6b8f56u, 0xff6b8f56u},
+{0xb2691b0bu, 0x1043c83du, 0xb2691b0bu},
+{0xb8463161u, 0xd153344au, 0xd153344au},
+{0x5ed14f9fu, 0x895cd7e1u, 0x5ed14f9fu},
+{0x3a5554a9u, 0x414bdaa0u, 0x414bddf5u},
+{0x858816aau, 0x18a6ff3eu, 0x18a6ff3eu},
+{0x969f4670u, 0x54449a0du, 0x54449a0du},
+{0xf2572705u, 0x28530f84u, 0xf2572705u},
+{0x2f18c41fu, 0x09a588bcu, 0x2f18c41fu},
+{0x6536b63fu, 0xf51ef9a8u, 0xf51ef9a8u},
+{0x7f098977u, 0x99ca1b67u, 0x7f098977u},
+{0x7a917520u, 0x74822e5cu, 0x7a917d43u},
+{0xcf59b1a6u, 0xee20d141u, 0xee20d141u},
+{0x683a9454u, 0x30d20e7au, 0x683a9454u},
+{0x67cc30a0u, 0xa4b9438du, 0x67cc30a0u},
+{0x04a7466du, 0x40c37e02u, 0x40c37e02u},
+{0x17fceef2u, 0x7f800000u, 0x7f800000u},
+{0xe1ff961au, 0x82968c65u, 0xe1ff961au},
+{0x20cdabc5u, 0x813c18efu, 0x20cdabc5u},
+{0x0af7e9e2u, 0xacd74339u, 0xacd74339u},
+{0x128fe80du, 0xfa6e701eu, 0xfa6e701eu},
+{0x23dd4757u, 0x44e83cffu, 0x44e83cffu},
+{0x5d007ecdu, 0x12249f58u, 0x5d007ecdu},
+{0x8006fa06u, 0x72960f9bu, 0x72960f9bu},
+{0x8eccbc84u, 0x53ed23a8u, 0x53ed23a8u},
+{0x77516f2cu, 0x871b0270u, 0x77516f2cu},
+{0x7ddb6c10u, 0x88626af0u, 0x7ddb6c10u},
+{0xcfd6ab12u, 0x6a74cab3u, 0x6a74cab3u},
+{0x01e4a162u, 0x34d1bef7u, 0x34d1bef7u},
+{0xe1358d16u, 0x3cc032abu, 0xe1358d16u},
+{0x6703c00du, 0xcbc12e9fu, 0x6703c00du},
+{0xee14d0eau, 0xdd9b332au, 0xee14d0eau},
+{0xc8636727u, 0x24c4f478u, 0xc8636727u},
+{0x9400b69fu, 0xb39a1d4fu, 0xb39a1d4fu},
+{0x92a09f76u, 0xaf0d2442u, 0xaf0d2442u},
+{0xfd4ee78au, 0x524d9104u, 0xfd4ee78au},
+{0x1a32dae6u, 0x2eae2732u, 0x2eae2732u},
+{0x05f1260au, 0xde0cc933u, 0xde0cc933u},
+{0xd3025d2du, 0x60913f5fu, 0x60913f5fu},
+{0x24bc524fu, 0xd9831dc5u, 0xd9831dc5u},
+{0x6d81c96bu, 0xd0cb61d3u, 0x6d81c96bu},
+{0x68c707c3u, 0xea221649u, 0xea093551u},
+{0xea77eaacu, 0x4998c6dfu, 0xea77eaacu},
+{0xc928d651u, 0x3f0cdeb1u, 0xc928d648u},
+{0xca1b784bu, 0xd2762a9fu, 0xd2762b3au},
+{0xf4104d1fu, 0xae39433eu, 0xf4104d1fu},
+{0x75cfa5c3u, 0x7eeee2a3u, 0x7eeee2d7u},
+{0x64333e8bu, 0x59540280u, 0x64333e8eu},
+{0xd59f709eu, 0x1159485bu, 0xd59f709eu},
+{0x7c9d7b74u, 0xa52088bau, 0x7c9d7b74u},
+{0xe029f2afu, 0x7c011f7au, 0x7c011f7au},
+{0xff800000u, 0x6689b5a1u, 0xff800000u},
+{0xbc0f739cu, 0xe5e106e6u, 0xe5e106e6u},
+{0x33ecca2du, 0xc08a0e30u, 0xc08a0e30u},
+{0x0c6d796au, 0x401b22f9u, 0x401b22f9u},
+{0xb63fda67u, 0x1f3e2279u, 0xb63fda67u},
+{0x7408e4f7u, 0x5bfa7d16u, 0x7408e4f7u},
+{0x70952b5bu, 0xc5cb9577u, 0x70952b5bu},
+{0x19c9dc2cu, 0xb628c8e5u, 0xb628c8e5u},
+{0x8af39343u, 0x2ae6420cu, 0x2ae6420cu},
+{0x38aa9493u, 0x61a645d7u, 0x61a645d7u},
+{0x46a2a588u, 0x35268445u, 0x46a2a588u},
+{0x59a41830u, 0x4a36ced8u, 0x59a41830u},
+{0x960182fbu, 0xda8f2b15u, 0xda8f2b15u},
+{0x9d519671u, 0x9abc613eu, 0x9d57797bu},
+{0x582aab94u, 0xb85c7512u, 0x582aab94u},
+{0x326026a5u, 0x8be473f2u, 0x326026a5u},
+{0xe30dfae7u, 0xa7d7a151u, 0xe30dfae7u},
+{0x57780769u, 0xb4a8508eu, 0x57780769u},
+{0xa08f5785u, 0x3b909eecu, 0x3b909eecu},
+{0x241fc07cu, 0x5acc2b9du, 0x5acc2b9du},
+{0xe2352470u, 0xf29fae71u, 0xf29fae71u},
+{0x773322d3u, 0xd102d545u, 0x773322d3u},
+{0x66929d31u, 0x31f76096u, 0x66929d31u},
+{0x6cd97ef7u, 0x2bb10cabu, 0x6cd97ef7u},
+{0xcd1737ecu, 0xcba5153fu, 0xcd2bda94u},
+{0xa32c9b15u, 0xdd336540u, 0xdd336540u},
+{0xac53fd1du, 0x0e769c08u, 0xac53fd1du},
+{0x2c201a4cu, 0x0d96b987u, 0x2c201a4cu},
+{0x51c834b5u, 0x5925ff2eu, 0x592600beu},
+{0xf23be03bu, 0x0734de04u, 0xf23be03bu},
+{0xd150fd77u, 0x100639e1u, 0xd150fd77u},
+{0x95847414u, 0x05e5d6b9u, 0x95847414u},
+{0xef71e973u, 0x21e48d97u, 0xef71e973u},
+{0x86bf94e9u, 0x25b30e7au, 0x25b30e7au},
+{0x04b1a2eau, 0xaf39c793u, 0xaf39c793u},
+{0xe14553a4u, 0x778025ccu, 0x778025ccu},
+{0x65e19b99u, 0x357ef874u, 0x65e19b99u},
+{0xd8e3766du, 0x3931f260u, 0xd8e3766du},
+{0x4d1582d4u, 0x5810ceb3u, 0x5810ceb5u},
+{0xd0926a1fu, 0x1a009fdau, 0xd0926a1fu},
+{0x0a6e0a66u, 0x72f79857u, 0x72f79857u},
+{0xc2ca8a71u, 0x35c9743fu, 0xc2ca8a71u},
+{0xbf666134u, 0xa60ed057u, 0xbf666134u},
+{0xfef641a2u, 0xb67a461fu, 0xfef641a2u},
+{0xa480af6du, 0x59a9d83au, 0x59a9d83au},
+{0xd21e440fu, 0xc5562d5fu, 0xd21e440fu},
+{0xbf8940b4u, 0xe6228331u, 0xe6228331u},
+{0xe927ef3au, 0x95dbcaf9u, 0xe927ef3au},
+{0x427bd98au, 0xa6bfd2fcu, 0x427bd98au},
+{0x6b8ae283u, 0x6b07cdb7u, 0x6bcec95eu},
+{0xae259d46u, 0x0f42914cu, 0xae259d46u},
+{0x108ea71cu, 0x4c98b402u, 0x4c98b402u},
+{0x47526bfcu, 0x2aff6271u, 0x47526bfcu},
+{0xb085879cu, 0x6c2f0dceu, 0x6c2f0dceu},
+{0x9ad5cf97u, 0x18f2fcfcu, 0x9ac69fc7u},
+{0xfa115742u, 0x98969070u, 0xfa115742u},
+{0x56970281u, 0xbf289e8cu, 0x56970281u},
+{0x9407c090u, 0xa5559116u, 0xa5559116u},
+{0x0c5e5c48u, 0xc93e3d42u, 0xc93e3d42u},
+{0xde69a0ccu, 0x97aa3467u, 0xde69a0ccu},
+{0x5b95aa4du, 0x36df19cdu, 0x5b95aa4du},
+{0xcb98c0cau, 0x846205e0u, 0xcb98c0cau},
+{0x8dd13af1u, 0x76fc0720u, 0x76fc0720u},
+{0xea5f0845u, 0x9704c19fu, 0xea5f0845u},
+{0xff800000u, 0x1aac6ba1u, 0xff800000u},
+{0x4e0f44feu, 0x3be2434fu, 0x4e0f44feu},
+{0x88ee57e4u, 0x7df0ddd8u, 0x7df0ddd8u},
+{0xf0d7631eu, 0xc937641eu, 0xf0d7631eu},
+{0x34d08309u, 0xac6833c5u, 0x34d08295u},
+{0xc5a87813u, 0xa2f25ae2u, 0xc5a87813u},
+{0xbf4e6c85u, 0x030f3f1cu, 0xbf4e6c85u},
+{0x91dd6bcdu, 0x25aea118u, 0x25aea118u},
+{0x07e75c4eu, 0xe7c8c7f3u, 0xe7c8c7f3u},
+{0x70caf24bu, 0x90e7e3fau, 0x70caf24bu},
+{0x5321dfa0u, 0xd6e9a07du, 0xd6e85cbeu},
+{0xa88ec5a6u, 0xac4156bbu, 0xac427446u},
+{0x43021ba5u, 0x80f10da0u, 0x43021ba5u},
+{0xcc340c2eu, 0x306cae4eu, 0xcc340c2eu},
+{0x6dc3cabcu, 0x3afaf063u, 0x6dc3cabcu},
+{0x2ec4e90bu, 0xa40a3223u, 0x2ec4e907u},
+{0x3225f648u, 0xb6648f16u, 0xb663e920u},
+{0xca47525fu, 0x176ded7au, 0xca47525fu},
+{0xe6d711ccu, 0x68b07ec0u, 0x68a30da3u},
+{0x04e49851u, 0x8af76a57u, 0x8af75c0du},
+{0x0e158411u, 0xe2a8faedu, 0xe2a8faedu},
+{0x4645574eu, 0x27c592abu, 0x4645574eu},
+{0x626e2802u, 0x3fa4214fu, 0x626e2802u},
+{0x1372e532u, 0xe7dfe914u, 0xe7dfe914u},
+{0xfe1bafe0u, 0xbfe5507bu, 0xfe1bafe0u},
+{0xadd17863u, 0x5afecd28u, 0x5afecd28u},
+{0x5569ea47u, 0x4571b0feu, 0x5569ea47u},
+{0xc963b477u, 0x7b5f95e2u, 0x7b5f95e2u},
+{0x3de1ff85u, 0x2b2031b4u, 0x3de1ff85u},
+{0xed2add10u, 0xca1b9b58u, 0xed2add10u},
+{0x3199488fu, 0x50612b90u, 0x50612b90u},
+{0x22ef79f3u, 0xc9a10bc7u, 0xc9a10bc7u},
+{0xfde354c4u, 0x5d288ae7u, 0xfde354c4u},
+{0xac3dbfe1u, 0x7679deedu, 0x7679deedu},
+{0x7de270b8u, 0x9d0286adu, 0x7de270b8u},
+{0x52096fd5u, 0xccf17aa0u, 0x520951a6u},
+{0xe9da623eu, 0x7124268au, 0x712424d5u},
+{0x7258778fu, 0x051f1c95u, 0x7258778fu},
+{0xe79b3c26u, 0xedc27b4bu, 0xedc284ffu},
+{0x1bbc6349u, 0xf0498791u, 0xf0498791u},
+{0xeb779179u, 0x260fbcacu, 0xeb779179u},
+{0x6e32b3a2u, 0x23554228u, 0x6e32b3a2u},
+{0x7f800000u, 0x55bcc2aeu, 0x7f800000u},
+{0x1b94a68fu, 0x720e7e80u, 0x720e7e80u},
+{0x4976b875u, 0x40ed589du, 0x4976b8ecu},
+{0x8edda7ffu, 0x0ae45fadu, 0x8edcc39fu},
+{0x06cb25f4u, 0xb0459d5fu, 0xb0459d5fu},
+{0x07d389edu, 0xa57031b8u, 0xa57031b8u},
+{0x059d1993u, 0xe1adc72fu, 0xe1adc72fu},
+{0x7a3e9d6cu, 0x3a8f512cu, 0x7a3e9d6cu},
+{0x5dc10191u, 0xf78bc6c8u, 0xf78bc6c8u},
+{0x3cd0de92u, 0x9d6a7a07u, 0x3cd0de92u},
+{0xe46c7aabu, 0x2ffdae7cu, 0xe46c7aabu},
+{0x7711cd20u, 0x462fb683u, 0x7711cd20u},
+{0x39a61b3cu, 0x0c10c8e4u, 0x39a61b3cu},
+{0x054c9477u, 0x942c49e9u, 0x942c49e9u},
+{0x688c3b7au, 0x7182fcadu, 0x7182fcd0u},
+{0xdd0c9ba4u, 0xa6a43aa5u, 0xdd0c9ba4u},
+{0x6e8c67acu, 0xa1b45cc4u, 0x6e8c67acu},
+{0xe51de0c0u, 0x555475f1u, 0xe51de0c0u},
+{0x298e70cbu, 0x1e17e88eu, 0x298e70ccu},
+{0xe59a0deeu, 0x7736d8c5u, 0x7736d8c5u},
+{0xe9903f24u, 0x6fc43ac5u, 0x6fc431c1u},
+{0x5cbcec1au, 0x92a6a5e3u, 0x5cbcec1au},
+{0xf29f9605u, 0x8ba91fcfu, 0xf29f9605u},
+{0x2c1a56b6u, 0x163ff868u, 0x2c1a56b6u},
+{0x2c22a0bbu, 0x138501b8u, 0x2c22a0bbu},
+{0xb664c7f2u, 0xb290b2d3u, 0xb665e958u},
+{0xc2f36ffeu, 0xaf4daed0u, 0xc2f36ffeu},
+{0xcef558a5u, 0x7e7793a8u, 0x7e7793a8u},
+{0x21a2ff7cu, 0x15f2e845u, 0x21a2ff7du},
+{0x06d17c3au, 0xdd9be90du, 0xdd9be90du},
+{0x493d42ffu, 0x4d2c6e85u, 0x4d2d2bc8u},
+{0xb01c766eu, 0x77ae5dfcu, 0x77ae5dfcu},
+{0xeaf339f1u, 0x7358cbfeu, 0x7358cb84u},
+{0xb577e808u, 0x9ca26b00u, 0xb577e808u},
+{0xdf946a54u, 0x9926c1bcu, 0xdf946a54u},
+{0xd516ccbbu, 0x51065514u, 0xd5164666u},
+{0xd866bacbu, 0x20ce0548u, 0xd866bacbu},
+{0xc18ba4d3u, 0x0a087aeau, 0xc18ba4d3u},
+{0x86ae6121u, 0xcb4fc5acu, 0xcb4fc5acu},
+{0x5379f624u, 0x7037d344u, 0x7037d344u},
+{0x1ba66126u, 0x429b4b7au, 0x429b4b7au},
+{0x4befa31fu, 0xdf9aa376u, 0xdf9aa376u},
+{0xa9c3f1efu, 0x11f14ef7u, 0xa9c3f1efu},
+{0xa3e97c6au, 0xaa6a7a34u, 0xaa6a8180u},
+{0x74a018ecu, 0x7bccd2c4u, 0x7bccd544u},
+{0x41b126d3u, 0x87b1f82cu, 0x41b126d3u},
+{0x7608086eu, 0xb3edae22u, 0x7608086eu},
+{0xb9cc63f2u, 0x226925a4u, 0xb9cc63f2u},
+{0xebabdcccu, 0xfd86a0e9u, 0xfd86a0e9u},
+{0x48f1e14bu, 0xc8216d7du, 0x48a12a8cu},
+{0x65dda831u, 0x958affd8u, 0x65dda831u},
+{0xa39a9130u, 0x28268cefu, 0x28263fa6u},
+{0x0ba4643bu, 0xf0a04698u, 0xf0a04698u},
+{0x903371eau, 0x41ec45ddu, 0x41ec45ddu},
+{0xeae86bdbu, 0x0d28ba9cu, 0xeae86bdbu},
+{0x82252fc6u, 0x421cfb28u, 0x421cfb28u},
+{0x74ddead7u, 0xdc7dbca8u, 0x74ddead7u},
+{0x8c5896c9u, 0xa9830eefu, 0xa9830eefu},
+{0xcbece1a5u, 0x9a6ab1fbu, 0xcbece1a5u},
+{0x2b10ce59u, 0xbb351011u, 0xbb351011u},
+{0x6cf85c3cu, 0x8cb8bf6bu, 0x6cf85c3cu},
+{0xfce39111u, 0xdda915bcu, 0xfce39111u},
+{0xb227c9ccu, 0x8414a483u, 0xb227c9ccu},
+{0xebb4a4c1u, 0x852d2914u, 0xebb4a4c1u},
+{0x1df4241du, 0x1b1637a3u, 0x1df8d5dau},
+{0x5d5dff0bu, 0xd458996fu, 0x5d5dfed5u},
+{0x82ed29b6u, 0x02b77c13u, 0x81d6b68cu},
+{0x3e01102cu, 0xc7cf2de8u, 0xc7cf2dd8u},
+{0xb6ad3b79u, 0xab1e8831u, 0xb6ad3b7au},
+{0x288e0513u, 0x1a969eddu, 0x288e0513u},
+{0xcc490562u, 0xd1830ee3u, 0xd1832804u},
+{0x7f13e094u, 0xb4714c76u, 0x7f13e094u},
+{0xb2a8e4e0u, 0xf7e86a90u, 0xf7e86a90u},
+{0x44b3dbbbu, 0x10c6981fu, 0x44b3dbbbu},
+{0x079538aeu, 0xbb8d0c84u, 0xbb8d0c84u},
+{0x94d72899u, 0x5395f837u, 0x5395f837u},
+{0x9dd64434u, 0xe888bdfdu, 0xe888bdfdu},
+{0xc54585eau, 0x633301f3u, 0x633301f3u},
+{0x8d9b35ddu, 0xed45db63u, 0xed45db63u},
+{0x1f436f86u, 0xbbba0ef4u, 0xbbba0ef4u},
+{0x553bbe73u, 0x5cceaaaeu, 0x5cceac25u},
+{0x03561a32u, 0x26e1bdecu, 0x26e1bdecu},
+{0x0b306025u, 0x3844f0b3u, 0x3844f0b3u},
+{0x4ccbe104u, 0x2c5fc60fu, 0x4ccbe104u},
+{0x8c574810u, 0x75ea8110u, 0x75ea8110u},
+{0xc71a5ac5u, 0x03615877u, 0xc71a5ac5u},
+{0x30cfdfa0u, 0x7f03ba12u, 0x7f03ba12u},
+{0xf09302fbu, 0xaa0cbeaau, 0xf09302fbu},
+{0x356540bdu, 0xaba10298u, 0x356540a9u},
+{0xa06f88fau, 0x52293906u, 0x52293906u},
+{0xd9da1119u, 0xe7f54e96u, 0xe7f54e96u},
+{0x53e71722u, 0x3b125256u, 0x53e71722u},
+{0x1284f080u, 0xe69d4697u, 0xe69d4697u},
+{0x6616160fu, 0x3a3277fcu, 0x6616160fu},
+{0xdb0f0c78u, 0x79e4af79u, 0x79e4af79u},
+{0xd032db73u, 0x87ac5842u, 0xd032db73u},
+{0x3b073e03u, 0x872cb8f1u, 0x3b073e03u},
+{0x421dc30du, 0x9c179c0bu, 0x421dc30du},
+{0x5b9ea312u, 0x9d2f18cau, 0x5b9ea312u},
+{0x01f19609u, 0x24043a9au, 0x24043a9au},
+{0xe5aa8fe8u, 0xe46be50bu, 0xe5c80c89u},
+{0x77caee1fu, 0x8a5afe49u, 0x77caee1fu},
+{0x96f3516du, 0x08f96d45u, 0x96f3516du},
+{0x15103c0du, 0x3b21942eu, 0x3b21942eu},
+{0x2e32d684u, 0x8bf94aecu, 0x2e32d684u},
+{0x1703faaeu, 0xa46de2ebu, 0xa46de2ebu},
+{0x6f539d4cu, 0xf85c2e7du, 0xf85c2e48u},
+{0xf76dd30du, 0x2752faf7u, 0xf76dd30du},
+{0x76ca022au, 0xbc1b3f9eu, 0x76ca022au},
+{0xa40de08au, 0xdeacc6ddu, 0xdeacc6ddu},
+{0xa4bde0c2u, 0xdd7ac73au, 0xdd7ac73au},
+{0xabb1ede6u, 0x5c7f6403u, 0x5c7f6403u},
+{0xa8736e06u, 0x0f1e105cu, 0xa8736e06u},
+{0xf0af00e5u, 0xd243c2bfu, 0xf0af00e5u},
+{0x4a246fb6u, 0x4e8bbadbu, 0x4e8c0d13u},
+{0x617207b2u, 0xde157b97u, 0x616fb1c4u},
+{0xeb5e866bu, 0x97c3fdb0u, 0xeb5e866bu},
+{0x802fdb74u, 0x8b4a4d49u, 0x8b4a4d49u},
+{0x66a9afd5u, 0xd56b948cu, 0x66a9afd5u},
+{0x7f343474u, 0xd31979adu, 0x7f343474u},
+{0xf56c99b7u, 0x07f3c717u, 0xf56c99b7u},
+{0x549a38a8u, 0xd5740235u, 0xd526e5e1u},
+{0x30eefa0eu, 0x7ecf6004u, 0x7ecf6004u},
+{0xdb8e2d22u, 0xb28ba59du, 0xdb8e2d22u},
+{0xd2acc74eu, 0xc6a795b5u, 0xd2acc74fu},
+{0x56e33d55u, 0x9bb4a554u, 0x56e33d55u},
+{0x178f5ca5u, 0xc7876343u, 0xc7876343u},
+{0xdf27f686u, 0xdf5d861au, 0xdfc2be50u},
+{0x29783a9eu, 0x18487e7au, 0x29783a9eu},
+{0x13d0b8deu, 0x172e4c06u, 0x172fed78u},
+{0x8f96d6e7u, 0xa4da01a1u, 0xa4da01a1u},
+{0x21f587f0u, 0xfa6d61edu, 0xfa6d61edu},
+{0xb0c53b67u, 0xe079983cu, 0xe079983cu},
+{0x8291fc69u, 0x96a8b3cau, 0x96a8b3cau},
+{0x7178692eu, 0xabeb1944u, 0x7178692eu},
+{0x8d5e0fb0u, 0xb46cc786u, 0xb46cc786u},
+{0x062728b7u, 0x48458029u, 0x48458029u},
+{0x93dd24a0u, 0xae13e132u, 0xae13e132u},
+{0xf322d177u, 0x3270123au, 0xf322d177u},
+{0x7aabe467u, 0xfe14cadbu, 0xfe137312u},
+{0x55e75d3au, 0x378ebe31u, 0x55e75d3au},
+{0x2d41ee14u, 0xf9dea0cfu, 0xf9dea0cfu},
+{0x2d0f107du, 0x6dccd2cdu, 0x6dccd2cdu},
+{0xb7152088u, 0xafb294acu, 0xb71521edu},
+{0x777c446bu, 0xfcf9c568u, 0xfcf9a5dfu},
+{0xc20764cfu, 0x4722cbe3u, 0x4722aa0au},
+{0x2ef49dfcu, 0xe13afd67u, 0xe13afd67u},
+{0x069b874bu, 0xb9366a1eu, 0xb9366a1eu},
+{0x043fbc42u, 0x2ec14f4au, 0x2ec14f4au},
+{0x8e57edc3u, 0xcb3171d7u, 0xcb3171d7u},
+{0x99ea59e0u, 0xfa5ce871u, 0xfa5ce871u},
+{0x4098e209u, 0x5820ad3du, 0x5820ad3du},
+{0x5c1589beu, 0x807b8d27u, 0x5c1589beu},
+{0x4460df73u, 0x557003a1u, 0x557003a1u},
+{0x710db01bu, 0xe7ae041fu, 0x710db005u},
+{0xc942b05du, 0x8b6e76dfu, 0xc942b05du},
+{0xad910816u, 0x0ae20d58u, 0xad910816u},
+{0x3b7809a8u, 0x90921b3du, 0x3b7809a8u},
+{0x91cfc455u, 0x120852c7u, 0x1101c272u},
+{0xfde4eef2u, 0x227575b2u, 0xfde4eef2u},
+{0x37bf6380u, 0x4cb96338u, 0x4cb96338u},
+{0x05f1fc28u, 0x181cb3edu, 0x181cb3edu},
+{0x76b3f3edu, 0x942836c5u, 0x76b3f3edu},
+{0xb6a50692u, 0xeb0ad06eu, 0xeb0ad06eu},
+{0x6e216effu, 0x61eeb64du, 0x6e216effu},
+{0x3c1f2566u, 0xb917787bu, 0x3c1cc784u},
+{0x89ab5550u, 0x5c05b7e4u, 0x5c05b7e4u},
+{0xaa585ccdu, 0xa1b700d9u, 0xaa585d29u},
+{0x4f1132d1u, 0x3d1a0f5fu, 0x4f1132d1u},
+{0xde0a5db9u, 0xa0d7e5fau, 0xde0a5db9u},
+{0xcd4b0274u, 0x8ac16583u, 0xcd4b0274u},
+{0xd645515fu, 0xb519e127u, 0xd645515fu},
+{0x98676ebeu, 0xb27decd6u, 0xb27decd6u},
+{0x5487d91au, 0x3170321bu, 0x5487d91au},
+{0xcf9dfb90u, 0x97a5a0c7u, 0xcf9dfb90u},
+{0x8a22ce3du, 0xbb6bec62u, 0xbb6bec62u},
+{0x40f36cdfu, 0xfe6e5656u, 0xfe6e5656u},
+{0x4b379b31u, 0x2f27bcc5u, 0x4b379b31u},
+{0x26ff4c1cu, 0xe8b606c2u, 0xe8b606c2u},
+{0x0d5b5c2cu, 0x4b1b095au, 0x4b1b095au},
+{0xef6bc353u, 0x7e00a9aeu, 0x7e00a9aeu},
+{0x4d8a56bdu, 0xb2822dbau, 0x4d8a56bdu},
+{0xe6bcdf53u, 0xdb2ac4deu, 0xe6bcdf54u},
+{0xbd09dd39u, 0xb71c0a4eu, 0xbd09e6fau},
+{0x25a3177au, 0x88c376e7u, 0x25a3177au},
+{0x24bc15a2u, 0x6dec97d5u, 0x6dec97d5u},
+{0x4ee5e1f9u, 0x3dca736au, 0x4ee5e1f9u},
+{0x1aa4a508u, 0xbbacdc60u, 0xbbacdc60u},
+{0x8916f0fbu, 0x87403ad0u, 0x8922f4a8u},
+{0xfb532aafu, 0x4ff51262u, 0xfb532aafu},
+{0x6ee6c6a3u, 0x6b11330cu, 0x6ee7e909u},
+{0x4e331b8fu, 0x61f0a4f1u, 0x61f0a4f1u},
+{0x1e5d484bu, 0x0aa3294au, 0x1e5d484bu},
+{0x0a481317u, 0xe56ec717u, 0xe56ec717u},
+{0x9dc884a8u, 0xd91db347u, 0xd91db347u},
+{0xbc62f251u, 0x1f5e7207u, 0xbc62f251u},
+{0x837e46cau, 0x3d6ff965u, 0x3d6ff965u},
+{0xc6bc45ebu, 0x22bbc0ecu, 0xc6bc45ebu},
+{0xb7e9efefu, 0x4aeb7053u, 0x4aeb7053u},
+{0x5a530f33u, 0xca96bcbau, 0x5a530f33u},
+{0x776c5e45u, 0x8a5b0a0cu, 0x776c5e45u},
+{0x4dde3d57u, 0x603b2bb3u, 0x603b2bb3u},
+{0x03795d65u, 0x90ffbf52u, 0x90ffbf52u},
+{0x0265f131u, 0x7f800000u, 0x7f800000u},
+{0x132d2f7cu, 0xeb323722u, 0xeb323722u},
+{0xc0afba17u, 0x2b7b143cu, 0xc0afba17u},
+{0x997e8180u, 0xe57aecd5u, 0xe57aecd5u},
+{0xe0086689u, 0x2cf8a888u, 0xe0086689u},
+{0x27346cefu, 0x6e36f2c2u, 0x6e36f2c2u},
+{0x81d30002u, 0x0334b70au, 0x031a570au},
+{0xf85466a2u, 0x3022d002u, 0xf85466a2u},
+{0xe253555du, 0xa60fa340u, 0xe253555du},
+{0x5128f5b8u, 0xe3574534u, 0xe3574534u},
+{0x1323195fu, 0x2f793fcau, 0x2f793fcau},
+{0x137b0c72u, 0xe5203df9u, 0xe5203df9u},
+{0x171622fau, 0x78f211e8u, 0x78f211e8u},
+{0x353f99ecu, 0xebd1d0f6u, 0xebd1d0f6u},
+{0x8c190029u, 0x1a16dc7au, 0x1a16dc7au},
+{0x1bc901b6u, 0xa7ce3fe8u, 0xa7ce3fe7u},
+{0x7538e7c7u, 0xc154f89cu, 0x7538e7c7u},
+{0xd88439a9u, 0x7f800000u, 0x7f800000u},
+{0xf807c86fu, 0x64332c2du, 0xf807c86fu},
+{0x0d069a37u, 0xf4bcd2c4u, 0xf4bcd2c4u},
+{0x5b228456u, 0x2461e3a9u, 0x5b228456u},
+{0xf7ea8fc6u, 0x750ba2fau, 0xf7e632aeu},
+{0xe983653au, 0xb6d81bccu, 0xe983653au},
+{0x7d23c7b8u, 0x972f981bu, 0x7d23c7b8u},
+{0x5c7cd175u, 0xc2e89647u, 0x5c7cd175u},
+{0x23a17884u, 0x7b122c15u, 0x7b122c15u},
+{0xb39b8ba2u, 0xc712e083u, 0xc712e083u},
+{0x40255382u, 0xc90238a9u, 0xc9023880u},
+{0x5bb3f219u, 0x36bcba8eu, 0x5bb3f219u},
+{0x59c1ee8au, 0x1bc4611cu, 0x59c1ee8au},
+{0x6d3963bdu, 0xbbc262f9u, 0x6d3963bdu},
+{0xd34b1140u, 0xaa657972u, 0xd34b1140u},
+{0x795c6228u, 0x9c0b382du, 0x795c6228u},
+{0xf09df3e1u, 0x45960f6cu, 0xf09df3e1u},
+{0xf6977096u, 0xe49abc78u, 0xf6977096u},
+{0x2109367au, 0x0cc85ea1u, 0x2109367au},
+{0xb5d4e11fu, 0x4ae99c90u, 0x4ae99c90u},
+{0x63c2db9eu, 0x41db5e2cu, 0x63c2db9eu},
+{0x62d953ffu, 0xf75229d6u, 0xf75229d6u},
+{0x8204d810u, 0x1ee2fd7eu, 0x1ee2fd7eu},
+{0x482c5c08u, 0x7a7f3625u, 0x7a7f3625u},
+{0x7e81429bu, 0x685db0c6u, 0x7e81429bu},
+{0x4a7106f4u, 0x353042adu, 0x4a7106f4u},
+{0x5db1b2bcu, 0xf32164cdu, 0xf32164cdu},
+{0xf61e6777u, 0x39f57fe2u, 0xf61e6777u},
+{0x3a168e3au, 0xfa8d12d1u, 0xfa8d12d1u},
+{0x7f681678u, 0x0fb87ec1u, 0x7f681678u},
+{0x2c8b126eu, 0x4c4c30a2u, 0x4c4c30a2u},
+{0x1cf4633fu, 0x34c12887u, 0x34c12887u},
+{0x18741a48u, 0x03e26ca5u, 0x18741a48u},
+{0xa2412606u, 0x5a629471u, 0x5a629471u},
+{0x1e961674u, 0x6c5dad58u, 0x6c5dad58u},
+{0xb430b6dcu, 0xed774f63u, 0xed774f63u},
+{0x24c9da46u, 0x6fcda227u, 0x6fcda227u},
+{0x2f1aa222u, 0x86039bcau, 0x2f1aa222u},
+{0xec1cdd4bu, 0x9422a1adu, 0xec1cdd4bu},
+{0xbdb9a3a0u, 0x67f8c966u, 0x67f8c966u},
+{0x73dffa00u, 0x98e66872u, 0x73dffa00u},
+{0xa1ff4e21u, 0x43583386u, 0x43583386u},
+{0x160f7415u, 0x54ed4360u, 0x54ed4360u},
+{0xc8379075u, 0x8dacda32u, 0xc8379075u},
+{0x9aaca607u, 0x6063e2deu, 0x6063e2deu},
+{0x89515730u, 0x7c97d273u, 0x7c97d273u},
+{0x068cd2b0u, 0xa9244fe2u, 0xa9244fe2u},
+{0xefddb149u, 0x01052115u, 0xefddb149u},
+{0x79ea5092u, 0x6c9530b4u, 0x79ea5092u},
+{0x7c2186b4u, 0xc92469f1u, 0x7c2186b4u},
diff --git a/test/pico_float_test/vectors/hazard3_mulsf.inc b/test/pico_float_test/vectors/hazard3_mulsf.inc
new file mode 100644
index 000000000..63c6c0a5a
--- /dev/null
+++ b/test/pico_float_test/vectors/hazard3_mulsf.inc
@@ -0,0 +1,1000 @@
+{0xa8c36b34u, 0x420ac26bu, 0xab53d866u},
+{0xd4cf10fbu, 0x692b079au, 0xfe8a567eu},
+{0xece2254du, 0xf36c2cbbu, 0x7f800000u},
+{0x34f22bceu, 0x7c3b1110u, 0x71b0f624u},
+{0x8b187e6fu, 0xa51e4bfcu, 0x00000000u},
+{0x0fe7c179u, 0xf0dcc0beu, 0xc147d8c1u},
+{0x768e7ddbu, 0x2ccdc929u, 0x63e51580u},
+{0x06f19a7fu, 0x07562985u, 0x00000000u},
+{0xa20ff19cu, 0xa6a951a3u, 0x093e68ceu},
+{0x64120a7fu, 0x935577e7u, 0xb7f38e45u},
+{0x900ed7f5u, 0x970a63d2u, 0x00000000u},
+{0xec7a91c8u, 0x00eb6ee1u, 0xade67059u},
+{0x87e4daa6u, 0xc88e8901u, 0x10fed784u},
+{0xf005a09du, 0xcbf5a56eu, 0x7c803910u},
+{0x112e23edu, 0x7be85175u, 0x4d9e07f8u},
+{0x04f3339au, 0x3a78a8b1u, 0x00000000u},
+{0x0a3232f6u, 0xea32f851u, 0xb4f92892u},
+{0xc98f9ea4u, 0xebf90ffbu, 0x760bba45u},
+{0xed8bd406u, 0x9502d86fu, 0x430eefc5u},
+{0x0ab44d09u, 0x940a9806u, 0x80000000u},
+{0x53117f9fu, 0x53160ff3u, 0x66aa93b0u},
+{0x455cf9c4u, 0x091efc06u, 0x0f093bb2u},
+{0x9d04dffdu, 0x9edd80dfu, 0x00000000u},
+{0x90c2fa22u, 0x93b5cbacu, 0x00000000u},
+{0x3c093424u, 0x9c303566u, 0x98bce0eeu},
+{0xd24a550du, 0x407dcb3au, 0xd34896adu},
+{0xd2d5e0d8u, 0xca9b966au, 0x5e01fccdu},
+{0x72d858b8u, 0x4c1960eeu, 0x7f800000u},
+{0x9a63d2c3u, 0xcb110969u, 0x260112c0u},
+{0xe45bfe13u, 0xfc3a9028u, 0x7f800000u},
+{0x57c64c27u, 0x5273314du, 0x6abc6079u},
+{0xa72f1718u, 0xc739117fu, 0x2efd274fu},
+{0x90cdb148u, 0x2eabbf2eu, 0x80000000u},
+{0xb2b429d1u, 0x821353fdu, 0x00000000u},
+{0xe202a662u, 0x62997577u, 0xff800000u},
+{0xc60df1c6u, 0xed07b0f2u, 0x73967938u},
+{0x471b9543u, 0x08082cefu, 0x0fa58535u},
+{0x6455a3a1u, 0x45398a87u, 0x6a1ad6dau},
+{0x29186441u, 0x62e3a555u, 0x4c878351u},
+{0xe2c75f26u, 0x3599d32eu, 0xd8ef98aau},
+{0xf4bebe05u, 0xcb41a1a2u, 0x7f800000u},
+{0xc76ef852u, 0xd3598bb3u, 0x5b4b12e5u},
+{0xc05c09e9u, 0x632ab30au, 0xe412b878u},
+{0xc2cf6165u, 0xfb0298c1u, 0x7e539667u},
+{0xdef32a63u, 0x8cf06bb1u, 0x2c645e08u},
+{0x6309cbb1u, 0xe35417fau, 0xff800000u},
+{0x6d985555u, 0xf5175c80u, 0xff800000u},
+{0xe9ff5030u, 0x6756d007u, 0xff800000u},
+{0xa422e9a4u, 0xaac9bd17u, 0x0f8061c7u},
+{0x9f73dbe2u, 0xd5eff474u, 0x35e49324u},
+{0x79b20fb8u, 0x47ac4525u, 0x7f800000u},
+{0x79657aebu, 0x1f618dc6u, 0x594a301fu},
+{0x5634c9a9u, 0x7be5371fu, 0x7f800000u},
+{0xfdee3dc7u, 0x2e8e3e83u, 0xed046071u},
+{0x5a1ac874u, 0x13a1d923u, 0x2e43b6b4u},
+{0x16b2d812u, 0xdd6d97ebu, 0xb4a5fc2au},
+{0x9ed19073u, 0x76251aa0u, 0xd58727e6u},
+{0x8da689c9u, 0x879b3f68u, 0x00000000u},
+{0x286d1e51u, 0xfa5a7310u, 0xe34a5664u},
+{0x056fd052u, 0x69d08989u, 0x2fc35a19u},
+{0xc817e61au, 0xc10685d9u, 0x499fa3bau},
+{0xf9f6dd82u, 0x2a8478c0u, 0xe4ff7d50u},
+{0xf8dda0c4u, 0x2199c318u, 0xdb051dfbu},
+{0x12be4771u, 0x93f7babeu, 0x80000000u},
+{0x87025952u, 0x7343aac6u, 0xbac741fbu},
+{0xad1d7a9bu, 0x7719cbf0u, 0xe4bd3775u},
+{0x54f5897bu, 0xb35f912eu, 0xc8d66e01u},
+{0xf7e27b8fu, 0x70e0c4d7u, 0xff800000u},
+{0x3d616a83u, 0xde7053eeu, 0xdc539dc2u},
+{0x587d62edu, 0x049ebffbu, 0x1d9d2114u},
+{0x69ca38e3u, 0xa5c40679u, 0xd01ad8abu},
+{0x4c69735du, 0x523e190du, 0x5f2d5a77u},
+{0x63cd7aafu, 0x5efe2fe2u, 0x7f800000u},
+{0xd58fc30fu, 0xbdb01383u, 0x53c5c21fu},
+{0x16c7da66u, 0xee4c113eu, 0xc59f4f7fu},
+{0x5e04dbefu, 0x6dba378fu, 0x7f800000u},
+{0xc446094fu, 0x9ec4300du, 0x2397c44cu},
+{0xb45c7b1au, 0xbf9add0au, 0x3485606du},
+{0x527a78acu, 0xa9ec462fu, 0xbce72beau},
+{0x9c859f1bu, 0x326a03a0u, 0x8f744aa6u},
+{0x1ecdbc33u, 0xd4deca58u, 0xb4330bd1u},
+{0xc491b64du, 0xe4999dfbu, 0x69aedfbfu},
+{0xea0d3b6du, 0x152c5167u, 0xbfbe21acu},
+{0x6800639du, 0x9a7c0071u, 0xc2fcc48eu},
+{0x4e5ab470u, 0x2524d77fu, 0x340cd3b2u},
+{0xde821748u, 0x9a314294u, 0x393427dcu},
+{0xd7d90f91u, 0x9dfddaf5u, 0x36573e09u},
+{0x9a6e422fu, 0x11ea2cb0u, 0x80000000u},
+{0xfa305a4du, 0x9f8ef775u, 0x5a44f91du},
+{0x7f800000u, 0x7ecf8ff4u, 0x7f800000u},
+{0xf7dae75au, 0x5b89388du, 0xff800000u},
+{0x8ad2ce1bu, 0xfd15989eu, 0x48765f44u},
+{0x8549054fu, 0x0715aa2fu, 0x80000000u},
+{0x08df8085u, 0x3290efa7u, 0x00000000u},
+{0xf9b05b50u, 0x45e3e467u, 0xff800000u},
+{0xd618c7aau, 0x1a21e62eu, 0xb0c13de2u},
+{0xb3e9d07du, 0x448a2a2au, 0xb8fc61ccu},
+{0x0817d23eu, 0x0e17145bu, 0x00000000u},
+{0xf04863cfu, 0xb0dd3e34u, 0x61ad2edbu},
+{0x85638413u, 0x621f50a4u, 0xa80d96b3u},
+{0x9a347165u, 0x1ecf7f68u, 0x80000000u},
+{0xaf5ada17u, 0x7552e217u, 0xe534482fu},
+{0x21533a8eu, 0x8b0c2dccu, 0x80000000u},
+{0x18191651u, 0x6543b033u, 0x3dea0abbu},
+{0xc571ce01u, 0x53ea5287u, 0xd9dd5440u},
+{0xbb28e01cu, 0x473d6337u, 0xc2f9ddcfu},
+{0xc8a926bau, 0x4e62c441u, 0xd795d5ddu},
+{0x86e68079u, 0xac7bd4d7u, 0x00000000u},
+{0x47c8f07cu, 0x3cc49f10u, 0x451a54f9u},
+{0x51021af4u, 0x5f10c5b9u, 0x7093274cu},
+{0xe4632eb6u, 0x6b2d427fu, 0xff800000u},
+{0xedc45634u, 0x5cdda5e6u, 0xff800000u},
+{0xb84b8830u, 0x5b9592bcu, 0xd46dd5dau},
+{0x8938d3f5u, 0xca4e93a0u, 0x14152524u},
+{0x12719b2bu, 0x9c8e3423u, 0x80000000u},
+{0xb8bd54e7u, 0x7a605659u, 0xf3a5ea26u},
+{0x06ec8b7eu, 0x5db893fbu, 0x252a8cffu},
+{0xf4ebdffeu, 0x40b27058u, 0xf6246942u},
+{0x23350fafu, 0x98728c6au, 0x80000000u},
+{0x706b89e4u, 0xddcfca5fu, 0xff800000u},
+{0xa5d39e54u, 0xdfd530dcu, 0x46303b1fu},
+{0x1be13ddeu, 0xe872fa18u, 0xc4d5c887u},
+{0x77f1e5ccu, 0xcd2aace2u, 0xff800000u},
+{0x2ba740c0u, 0xcd4f0df0u, 0xb9874676u},
+{0xec00d47au, 0xe8afd26au, 0x7f800000u},
+{0xc4edce44u, 0xfc8ee969u, 0x7f800000u},
+{0x9be790c0u, 0x9e5342e7u, 0x00000000u},
+{0x9c3e0849u, 0xc0407137u, 0x1d0eda41u},
+{0x74d95ccau, 0x499ec4d6u, 0x7f06ce65u},
+{0x4252fc0au, 0xaec0d9ceu, 0xb19ef089u},
+{0x5e1ebb93u, 0xa8859ebdu, 0xc725b3c1u},
+{0x0d0175c2u, 0x7c008c86u, 0x498203e2u},
+{0x250b16bdu, 0x407f9125u, 0x260ada82u},
+{0x296e1ea4u, 0x87e1aae2u, 0x80000000u},
+{0xf4aba78eu, 0x2ef60552u, 0xe424f694u},
+{0x1d82e696u, 0xdeafc368u, 0xbcb3bf17u},
+{0xfcad4897u, 0x6b27581fu, 0xff800000u},
+{0xb5298a46u, 0x2935b912u, 0x9ef0b2a9u},
+{0x53cc8f9eu, 0xeb6bcce3u, 0xff800000u},
+{0x554e7b84u, 0x53d11e1eu, 0x69a8ab21u},
+{0x22688415u, 0x70958cc3u, 0x5387d4bau},
+{0x152672b2u, 0x9a60547fu, 0x80000000u},
+{0x14deaf74u, 0x50655ae7u, 0x25c78205u},
+{0x4bbb9cf8u, 0xebebf934u, 0xf82cefb9u},
+{0x164083e6u, 0x4b5d0277u, 0x222633b8u},
+{0x1fd0f48bu, 0x92716a0bu, 0x80000000u},
+{0xd57bc2cdu, 0x7a392010u, 0xff800000u},
+{0xfe8230beu, 0x3b624f0au, 0xfa662e74u},
+{0x8bce666bu, 0x1324deadu, 0x80000000u},
+{0x58961825u, 0x74813fddu, 0x7f800000u},
+{0x9463214bu, 0x3b2f08e5u, 0x901b4ba6u},
+{0xe701da5fu, 0x8e7b3a11u, 0x35fedd1eu},
+{0x0350403eu, 0xf613e135u, 0xb9f0982eu},
+{0x3b3e2a49u, 0xc31f1bcdu, 0xbeec61d4u},
+{0xa73d56afu, 0x5ed1c217u, 0xc69b2352u},
+{0xf9ef302cu, 0x3cea9b94u, 0xf75b3365u},
+{0x7698bdb0u, 0x4f66c1e6u, 0x7f800000u},
+{0xd4ec1ba4u, 0xacc6705au, 0x42370500u},
+{0x90e88632u, 0x07c44193u, 0x80000000u},
+{0x6010566eu, 0x91ac29ffu, 0xb242237fu},
+{0xfa3447b4u, 0xbc8fd826u, 0x774a988au},
+{0xcd4db5c2u, 0xe98c545du, 0x77618661u},
+{0x77f16de5u, 0xd4ec082eu, 0xff800000u},
+{0x541fb093u, 0xfb6de113u, 0xff800000u},
+{0x56c1453fu, 0xe86d86ffu, 0xff800000u},
+{0xd81da361u, 0x792a4904u, 0xff800000u},
+{0x664cd3b5u, 0xc4e298f4u, 0xebb54d47u},
+{0xc0f9fcceu, 0xcae84da2u, 0x4c62d8eau},
+{0xce9ee780u, 0x8d978179u, 0x1cbc15d5u},
+{0x0e9ce349u, 0x792a101du, 0x4850719du},
+{0x86e2f8beu, 0xcc52355bu, 0x13ba5f5au},
+{0x04cf751fu, 0xe5db081eu, 0xab317fc5u},
+{0xf3ef93bcu, 0x422c4ea0u, 0xf6a140d7u},
+{0x264db607u, 0xd39183beu, 0xba69dbeeu},
+{0xd6bc3563u, 0x6a6190ccu, 0xff800000u},
+{0xb636fc08u, 0x7eb3e8feu, 0xf58098c4u},
+{0xa197dfa7u, 0xaedfa4b6u, 0x1104ad8au},
+{0x073b76f1u, 0xeebcaef0u, 0xb68a2b74u},
+{0xe5ee7e35u, 0x1bc60178u, 0xc23876fbu},
+{0x1c2744a1u, 0x630a7678u, 0x3fb4f0ceu},
+{0x0c497b83u, 0x918c5692u, 0x80000000u},
+{0x2a171d73u, 0xc9a434bfu, 0xb441dc01u},
+{0x823d1dcdu, 0x45f1b213u, 0x88b28c9bu},
+{0xc0506450u, 0x4623ebf1u, 0xc7056fefu},
+{0x9ae3c913u, 0x91050c92u, 0x00000000u},
+{0xff0ed2e2u, 0x517fcb19u, 0xff800000u},
+{0xc473b53bu, 0x78092ec6u, 0xfd029884u},
+{0x82032198u, 0xfb4cf76eu, 0x3dd1fb06u},
+{0x35980202u, 0xced3eeeeu, 0xc4fbaf0eu},
+{0xe7cedb64u, 0x296fd530u, 0xd1c1cb16u},
+{0x277ff958u, 0xe8d7f50eu, 0xd0d7ef71u},
+{0x2cad366bu, 0x9cfbfeb0u, 0x8a2a80aeu},
+{0x629f942au, 0x3ae81beeu, 0x5e10afafu},
+{0xa12cd2dcu, 0xfa8343ccu, 0x5c313b57u},
+{0x5be17669u, 0x4e60602fu, 0x6ac59c52u},
+{0x08524ce5u, 0xe5e1179fu, 0xaeb8e8fdu},
+{0xb537d098u, 0x6a53b86au, 0xe0180557u},
+{0x7f800000u, 0x1e181546u, 0x7f800000u},
+{0x84079f3au, 0x9862840fu, 0x00000000u},
+{0x45e156b9u, 0x6d717dfdu, 0x73d4918au},
+{0x7a106dedu, 0xdd9c293fu, 0xff800000u},
+{0x715c13b5u, 0x069f52a6u, 0x3888f74au},
+{0xfb3b0be7u, 0x96115bd2u, 0x51d469a9u},
+{0x653c8abfu, 0x5792ec21u, 0x7d586a12u},
+{0xd63ad2cfu, 0xbdcd9fc8u, 0x54960f6bu},
+{0x76494ff6u, 0xf168db59u, 0xff800000u},
+{0xd750f478u, 0x93df6f29u, 0x2bb65fb0u},
+{0x52591a58u, 0x62ce57f9u, 0x75aefdceu},
+{0x59702e0cu, 0xac4d4be9u, 0xc6409c18u},
+{0x191b4f82u, 0x9c120c0fu, 0x80000000u},
+{0x7571977du, 0x4868cd7au, 0x7e5bb333u},
+{0xe323810du, 0xfb7823ecu, 0x7f800000u},
+{0xd8a31d0bu, 0xb1bf5ae8u, 0x4af3d92eu},
+{0x9bbe493au, 0x9b621004u, 0x00000000u},
+{0x0c424697u, 0x65cdc27fu, 0x329c2621u},
+{0x7f800000u, 0x42683410u, 0x7f800000u},
+{0xab28f27fu, 0x59f8206du, 0xc5a3c051u},
+{0x6564bca0u, 0x9b1ff586u, 0xc10eec88u},
+{0xdec04178u, 0x5ed95714u, 0xfe2338e4u},
+{0x448371b4u, 0x5e3e357fu, 0x634353b7u},
+{0xa5f210b1u, 0xf94c0e02u, 0x5fc0f28cu},
+{0x24a6378eu, 0x44147833u, 0x2940cc52u},
+{0xb8c6ff13u, 0x1841bfe0u, 0x91969b74u},
+{0x69bb56dbu, 0x04da540au, 0x2f1fc576u},
+{0x5a32d3c0u, 0x5085d6e0u, 0x6b3afc38u},
+{0x86071b75u, 0xbd8a8247u, 0x0412331du},
+{0x5b0fde08u, 0x95f8f8afu, 0xb18bead9u},
+{0x1512023au, 0xc1c42a8eu, 0x975fc3f4u},
+{0xa4acb190u, 0xbb6ea9deu, 0x20a0ffabu},
+{0x18e7c2deu, 0xe277f7c4u, 0xbbe07d53u},
+{0xb1f9e28cu, 0x10fbeff2u, 0x8375eb56u},
+{0x7924eadeu, 0xbf64d412u, 0xf91369ccu},
+{0x789ef535u, 0x38f4a07eu, 0x7217e55eu},
+{0x021e8172u, 0xb9e650fau, 0x80000000u},
+{0xd8118d29u, 0xd11d6aafu, 0x69b30074u},
+{0xbdf63515u, 0xce2dab29u, 0x4ca7067cu},
+{0x5f8251f4u, 0x7e179812u, 0x7f800000u},
+{0xfbba6262u, 0x86b8f500u, 0x4306a917u},
+{0x93daea6du, 0x0879f2bdu, 0x80000000u},
+{0xa747d748u, 0x3ef33374u, 0xa6bdd984u},
+{0x44788a48u, 0xcf7689cfu, 0xd46f5aacu},
+{0xe102ff64u, 0xb1004639u, 0x52834742u},
+{0xb7c45bfbu, 0x6913675bu, 0xe1622030u},
+{0x7c7f098du, 0xfb75dedbu, 0xff800000u},
+{0x8c9c1595u, 0xc2472a61u, 0x0f72dd3bu},
+{0xb5385374u, 0x1ed8a0a7u, 0x949bfa16u},
+{0xddc4042cu, 0x3fc480cbu, 0xde1675cfu},
+{0x302472b2u, 0x5e5ab2c1u, 0x4f0c7c7fu},
+{0xe385760au, 0x5ec80bf3u, 0xff800000u},
+{0xa47e90d8u, 0x49275c5du, 0xae266c55u},
+{0x0fa782dcu, 0xc80110b6u, 0x9828e7c0u},
+{0xf541129bu, 0xed5cdcddu, 0x7f800000u},
+{0xbc8b5485u, 0x747c6604u, 0xf1895eb9u},
+{0x771a0bdbu, 0x75e87b47u, 0x7f800000u},
+{0x3cec3190u, 0xe16d9aceu, 0xdedb38b6u},
+{0x1b12dd4au, 0x006edd76u, 0x00000000u},
+{0x352d8890u, 0xca2a465du, 0xbfe6d8c4u},
+{0xd6b158e9u, 0x56874a5au, 0xedbb72cau},
+{0x3e768f34u, 0x4bd0e6d8u, 0x4ac932afu},
+{0xace8138au, 0x7323f795u, 0xe094a4e3u},
+{0x412bbacdu, 0xac93b408u, 0xae462a11u},
+{0xf50b7df4u, 0xeafe09a3u, 0x7f800000u},
+{0x1ca1a9eeu, 0xcf5fb2f1u, 0xac8d4407u},
+{0x503dfd5au, 0xa4754cecu, 0xb5360c8du},
+{0x0d8c13d9u, 0xe58a2542u, 0xb3972e2cu},
+{0xaaa3bafeu, 0x611228b6u, 0xcc3af55du},
+{0x1dd6ef19u, 0xae41e166u, 0x8ca2c780u},
+{0x7960b488u, 0xc272dc21u, 0xfc552be1u},
+{0xc0624f3du, 0x85dda8cfu, 0x06c3f3a3u},
+{0xbf08d4dfu, 0x6f988295u, 0xef230860u},
+{0x55d5eccdu, 0xfd108bedu, 0xff800000u},
+{0xaf756370u, 0x0da455dau, 0x80000000u},
+{0xadcb53f4u, 0x368d92f5u, 0xa4e0e3ecu},
+{0x17c23c65u, 0x19e687f3u, 0x00000000u},
+{0xfc56299cu, 0x109f5deeu, 0xcd85526cu},
+{0xb7283035u, 0x71112332u, 0xe8beb4dbu},
+{0xbe76e6aau, 0x0439471bu, 0x8332b145u},
+{0xa074b2deu, 0x7f5f1209u, 0xe055390du},
+{0xa6567493u, 0x79b164cfu, 0xe0949b0du},
+{0xb182b0c1u, 0x6ddfa43au, 0xdfe4579eu},
+{0x7bf2caa1u, 0x41edd18du, 0x7e618c54u},
+{0x0f0cdbd1u, 0x00b49f90u, 0x00000000u},
+{0xc3c51598u, 0x9c9a4211u, 0x20ed83b4u},
+{0xa2062836u, 0x3bfa8e6fu, 0x9e834de9u},
+{0x0c688981u, 0xb6e94aafu, 0x83d3e8fdu},
+{0x356120c8u, 0x2f2dd448u, 0x2518ddd6u},
+{0xcbcc6a19u, 0xe0ea5993u, 0x6d3b2081u},
+{0x36fa2bdcu, 0xf67a5019u, 0xedf49d1bu},
+{0x6d8a2515u, 0xe1169809u, 0xff800000u},
+{0xb9eb555fu, 0x4c9f1a43u, 0xc712422au},
+{0x980be345u, 0x64a8aa95u, 0xbd3854b7u},
+{0x7dd9393fu, 0x4f630044u, 0x7f800000u},
+{0x337bb1b8u, 0xf10d1928u, 0xe50ab99eu},
+{0xc0911657u, 0xa33438e5u, 0x244c47e8u},
+{0xa9bb3347u, 0xa89148a7u, 0x12d47a58u},
+{0x7012388eu, 0x46718003u, 0x7709f05cu},
+{0x2212b6f6u, 0x07b8720bu, 0x00000000u},
+{0x9e30abe1u, 0xf36ff0d6u, 0x522596acu},
+{0xf6fcba04u, 0x012a4b6au, 0xb8a81dfau},
+{0x34002f95u, 0x1f38e6a8u, 0x13b92b64u},
+{0xa6167252u, 0x7df22c86u, 0xe48e523cu},
+{0x780dcfe5u, 0x56aaa18du, 0x7f800000u},
+{0xf2c6de70u, 0x1fc965a9u, 0xd31c739fu},
+{0x2a512a46u, 0x958615aau, 0x80000000u},
+{0x36d7d88du, 0x02540181u, 0x00000000u},
+{0xda0c6e88u, 0x1082c61cu, 0xab0f799cu},
+{0x3e3d540au, 0x303538f1u, 0x2f060688u},
+{0xa049ce49u, 0x362c9ba2u, 0x97081149u},
+{0xe78410d2u, 0xf2398d43u, 0x7f800000u},
+{0xf1c83119u, 0x6a5280b4u, 0xff800000u},
+{0x5fed8b8au, 0xcde19518u, 0xee5151fdu},
+{0x33917d1au, 0xa64d153fu, 0x9a691a82u},
+{0x41bd6eb2u, 0x13f591d5u, 0x1635b6dau},
+{0xf293c81au, 0xf5aa50b0u, 0x7f800000u},
+{0x33052b7au, 0x440e4c2eu, 0x37940b7du},
+{0x23acc2cau, 0x375254b1u, 0x1b8df0f1u},
+{0x6bd2777du, 0xeba980f8u, 0xff800000u},
+{0x58564c9eu, 0x9a0e77c2u, 0xb2ee857fu},
+{0xea41abd4u, 0x9cb52c7cu, 0x47891024u},
+{0x1eb7498cu, 0x9d07a9c7u, 0x80000000u},
+{0x0c041629u, 0x07c78a87u, 0x00000000u},
+{0x0fca17dfu, 0x0b3ebf44u, 0x00000000u},
+{0x7aac6ddfu, 0xab105af2u, 0xe642761eu},
+{0xa5060a6fu, 0x4ff5594eu, 0xb58076bfu},
+{0xe874d8e9u, 0xa08cf274u, 0x4986ce83u},
+{0x1ebbc68fu, 0xe14d3d20u, 0xc0968ad6u},
+{0x0a734f2fu, 0xd7682c59u, 0xa25ca9e9u},
+{0xd87a3ddbu, 0x16427d5au, 0xaf3e1d68u},
+{0xaf429e20u, 0x1634d2d5u, 0x86097776u},
+{0xfacd5e20u, 0x3bb70e12u, 0xf712d992u},
+{0xe994c008u, 0x1ffa86f8u, 0xca1191f4u},
+{0xf198e8afu, 0x16fbfa58u, 0xc91681abu},
+{0xe276ba65u, 0x92077527u, 0x35028d34u},
+{0xbbdb544fu, 0x8529df27u, 0x019189d8u},
+{0x96322539u, 0x1954f1b0u, 0x80000000u},
+{0x084ef10cu, 0x977dc0acu, 0x80000000u},
+{0xba0eea2fu, 0x9007ef12u, 0x0a97c5ebu},
+{0x14bd40d9u, 0x66f6f196u, 0x3c368ee9u},
+{0x4cd666bfu, 0x70a378e5u, 0x7e08e8acu},
+{0x310c7409u, 0xf0facbc7u, 0xe289991eu},
+{0xe9a825edu, 0x4b9962f0u, 0xf5c97f4eu},
+{0x2a1c8022u, 0xa44aa6c1u, 0x8ef7c618u},
+{0xee7026c4u, 0xaab1b351u, 0x59a6b305u},
+{0xc649373eu, 0x37c9312au, 0xbe9e2304u},
+{0x2e582ab5u, 0x55ea2172u, 0x44c5b347u},
+{0x6816315eu, 0x3b9f3990u, 0x643ad4deu},
+{0x702d7689u, 0x9829509fu, 0xc8e573c2u},
+{0x9e4c45aau, 0xe7ed4d17u, 0x46bd5a02u},
+{0x635e1164u, 0x8c05f15eu, 0xafe860d2u},
+{0x1265ee75u, 0xe48855c3u, 0xb774e76bu},
+{0xec2594f2u, 0x560f551eu, 0xff800000u},
+{0xac92e4f0u, 0xe579984au, 0x528f3810u},
+{0x530db66cu, 0x1a8cf528u, 0x2e1c0ef2u},
+{0xbb886033u, 0xc2f78e20u, 0x3f03e088u},
+{0x5cafd674u, 0xe77c9f5bu, 0xff800000u},
+{0xe753a713u, 0x4055dbc2u, 0xe830cfb3u},
+{0xb024aae8u, 0x60a3e7acu, 0xd152dbadu},
+{0xd39b11a2u, 0x4f04aeb8u, 0xe320bddau},
+{0x5a19fc67u, 0xa53f10bcu, 0xbfe5dac3u},
+{0xe5d49601u, 0xe9638523u, 0x7f800000u},
+{0x5d012455u, 0xd4db479au, 0xf25d3c67u},
+{0xbcef46f5u, 0xf1027763u, 0x6e73e33eu},
+{0xdd276b4fu, 0xc454d96cu, 0x620b330eu},
+{0x79e9a56bu, 0xf16e7839u, 0xff800000u},
+{0xc9052bbeu, 0x721c661fu, 0xfba2b78fu},
+{0x93260226u, 0x72ace9c8u, 0xc6604216u},
+{0x52d03c64u, 0x1208d792u, 0x255e9eddu},
+{0xe85a4dfeu, 0xd2924c9cu, 0x7b79839eu},
+{0xb3d5f200u, 0xd76e0b9bu, 0x4bc6f0afu},
+{0x65e5e39cu, 0x64cf4d3au, 0x7f800000u},
+{0x28531053u, 0xbcb4a275u, 0xa594ed6bu},
+{0x21741210u, 0xc3241e74u, 0xa51c789bu},
+{0x4f87cbceu, 0xea71d988u, 0xfa804a41u},
+{0x6224d352u, 0x8a47e325u, 0xad00b284u},
+{0x92f2c7fdu, 0x4a685e4du, 0x9ddc5eacu},
+{0x41b80d2bu, 0xa5db46bau, 0xa81da61du},
+{0x3b1a60e4u, 0x2e0b5601u, 0x29a80cf2u},
+{0x996d731du, 0x639a8f42u, 0xbd8f5c20u},
+{0xf56d492eu, 0x5401ada1u, 0xff800000u},
+{0x1aaa1839u, 0x0dff892fu, 0x00000000u},
+{0xea1d082bu, 0x36a16841u, 0xe146042cu},
+{0x85aad29eu, 0x2f2914efu, 0x80000000u},
+{0xd42faa5fu, 0x6e3dd7fdu, 0xff800000u},
+{0xa758d276u, 0x867aed1du, 0x00000000u},
+{0xfd74de7bu, 0x369936d1u, 0xf4928d66u},
+{0x822562a5u, 0x2806f8edu, 0x80000000u},
+{0x82ee1c6du, 0xdf817b5au, 0x22f0de1du},
+{0xdf51878du, 0xf1a93b59u, 0x7f800000u},
+{0xe95f499au, 0xaa92bf54u, 0x547ffdb6u},
+{0x595664eeu, 0xecc9389au, 0xff800000u},
+{0x21ce5121u, 0xc499637bu, 0xa6f73d52u},
+{0x7d32eb15u, 0xb7a6d323u, 0xf5693000u},
+{0xa8cc4fedu, 0x554c1689u, 0xbea2e1adu},
+{0x98f28b4du, 0x3749b173u, 0x90bf177fu},
+{0x9f8d7cd8u, 0x1d4b5eedu, 0x80000000u},
+{0x46d628cfu, 0xf01abb5fu, 0xf781714cu},
+{0x879c02b2u, 0x4f1f5702u, 0x97423565u},
+{0x495519abu, 0xa44eaeaeu, 0xae2c0c10u},
+{0xbb6dd030u, 0x39b950ebu, 0xb5ac269eu},
+{0x0d970075u, 0xe4c5a03au, 0xb2e923b9u},
+{0x7f731ba9u, 0x8bc6d6abu, 0xcbbcd340u},
+{0x1b11d520u, 0x40153ee1u, 0x1baa09bbu},
+{0x1d8ab3b5u, 0x8a93ab32u, 0x80000000u},
+{0xbed2a503u, 0xbfc48856u, 0x3f21b685u},
+{0x6bb0242cu, 0x3af28fcau, 0x6726e521u},
+{0x2802d990u, 0xed1bbf90u, 0xd59f3748u},
+{0x2e4b9bfau, 0x83fd3fbbu, 0x80000000u},
+{0xb4d22465u, 0x638754e9u, 0xd8de2dc9u},
+{0x9aabc0a0u, 0x2109ee9eu, 0x80000000u},
+{0x9f780664u, 0x9999c4a0u, 0x00000000u},
+{0x31e671a8u, 0x3b9f803fu, 0x2e0f9409u},
+{0xd3fd5754u, 0xd7b5439fu, 0x6c3361aau},
+{0x93cc8660u, 0x3838c3a3u, 0x8c939ce2u},
+{0x8d7f6cfdu, 0xa17a2728u, 0x00000000u},
+{0x03b222f7u, 0xee8f7acfu, 0xb2c7adf9u},
+{0xd96e532cu, 0x3690c62eu, 0xd086c748u},
+{0xfbebba7cu, 0x3904c068u, 0xf5747aa7u},
+{0x3282ed92u, 0x2c2c8ef6u, 0x1f308177u},
+{0x2dab85e3u, 0x94e6d20eu, 0x831aa707u},
+{0xe8d32a7cu, 0x8256ca01u, 0x2bb12c24u},
+{0x7889cf38u, 0xb5d224e0u, 0xeee23fabu},
+{0x0a636b5au, 0xec449d6du, 0xb72eaa0bu},
+{0xaa864868u, 0xdbbaf35cu, 0x46c42085u},
+{0xdc1d82a7u, 0xc7a718adu, 0x644d9ed3u},
+{0x610affb1u, 0xe6a819c9u, 0xff800000u},
+{0x00bf372cu, 0x3dffe5b7u, 0x00000000u},
+{0x592d2cf2u, 0xa14b29c1u, 0xbb096ee3u},
+{0xe9e84611u, 0x45464a0cu, 0xefb3e960u},
+{0x45ab0c9bu, 0x008a0e28u, 0x06b87c82u},
+{0xae8501f8u, 0xd439b925u, 0x4340fd3cu},
+{0x92052ad0u, 0x35b22420u, 0x8839551fu},
+{0x4c2a5c49u, 0xc0e0b4cfu, 0xcd958913u},
+{0xf224cc4eu, 0xe7be3f12u, 0x7f800000u},
+{0x8c023902u, 0xda882ec9u, 0x270a8c2bu},
+{0xcb311bebu, 0xcdb382e9u, 0x5978622du},
+{0xf955196eu, 0xbd4323deu, 0x7722703au},
+{0x231bcb4eu, 0x7aa7a686u, 0x5e4c0defu},
+{0x5535c750u, 0x9e8b62b6u, 0xb445f2a0u},
+{0x1f28e619u, 0x3cd57406u, 0x1c8cd3ffu},
+{0xc9b949deu, 0xb6fba018u, 0x41361f4cu},
+{0x09324eebu, 0x9a02c096u, 0x80000000u},
+{0x48e2c7feu, 0x1d3fe94eu, 0x26aa01e4u},
+{0x959a8ad4u, 0x884398d1u, 0x00000000u},
+{0xc48b168du, 0x41570025u, 0xc669a009u},
+{0xe840a92eu, 0x61cc7839u, 0xff800000u},
+{0x8e8381c6u, 0x99fbbb84u, 0x00000000u},
+{0x2d4c9e48u, 0x1c851831u, 0x0a54c323u},
+{0x5f6646efu, 0xfec39eceu, 0xff800000u},
+{0xa387fddcu, 0x7a777ce0u, 0xde837845u},
+{0x5da27df5u, 0x6b535404u, 0x7f800000u},
+{0xb006758eu, 0x7e6fefa3u, 0xeefc0b3au},
+{0xb61d0982u, 0x0a52dae3u, 0x81015812u},
+{0x4b030676u, 0xc293e88fu, 0xce17677au},
+{0x17f6e095u, 0x2371352eu, 0x00000000u},
+{0x9f001e39u, 0xd784ae11u, 0x3704cd65u},
+{0xdd19e57eu, 0xbd305decu, 0x5ad40c7au},
+{0xc44d8484u, 0x6815117cu, 0xecef5854u},
+{0xf7957209u, 0x56afdde8u, 0xff800000u},
+{0x4eb667d5u, 0x7ecbdc8eu, 0x7f800000u},
+{0xf35f4aecu, 0xae5e2b7eu, 0x6241c8e8u},
+{0x0b87b91fu, 0x22eacbf2u, 0x00000000u},
+{0x553a2192u, 0x42eb13a2u, 0x58aaeb17u},
+{0x7cd2c724u, 0x3223fc12u, 0x6f870457u},
+{0xdb8e90a8u, 0xa7320869u, 0x43464a88u},
+{0xf2ced7edu, 0xe76503c5u, 0x7f800000u},
+{0x28121aa0u, 0x807f59bcu, 0x80000000u},
+{0xc53d5941u, 0xd5e068bcu, 0x5ba5fb90u},
+{0xff5558cdu, 0x6a243f83u, 0xff800000u},
+{0x71eb7177u, 0xf511b6f7u, 0xff800000u},
+{0x57d032b0u, 0x86ba91b5u, 0x9f17bb54u},
+{0x7ce7fb2du, 0xa50c93e7u, 0xe27ec6c6u},
+{0x76e3acfbu, 0x4f7fa720u, 0x7f800000u},
+{0xc1d44b81u, 0xd1999596u, 0x53feba59u},
+{0x8e235a21u, 0xa6340b42u, 0x00000000u},
+{0x2a468744u, 0x581936cbu, 0x42eda2abu},
+{0x42b348bcu, 0x666ac0d1u, 0x69a46785u},
+{0xf1d0d1dfu, 0xb56fedebu, 0x67c3b601u},
+{0x46e3ee25u, 0x9d4a5000u, 0xa4b42124u},
+{0x972f07aeu, 0x2db73d40u, 0x857a90bcu},
+{0x8c8ce88fu, 0x5cc175f9u, 0xa9d4f886u},
+{0xd4d33b08u, 0x028dc458u, 0x97e9f30au},
+{0xae0fdb42u, 0x0b464db2u, 0x80000000u},
+{0x9572f7b3u, 0xd892a113u, 0x2e8b2a24u},
+{0x800f9576u, 0xfa8a438cu, 0x00000000u},
+{0x37d39980u, 0x4cbde11eu, 0x451cf266u},
+{0x864e456fu, 0x588b9a67u, 0x9f60f838u},
+{0x09a55166u, 0xaae72998u, 0x80000000u},
+{0x84fd542bu, 0x4feebd32u, 0x956c3f79u},
+{0x01d74270u, 0xb10165ecu, 0x80000000u},
+{0xb40eb722u, 0x0ec24b47u, 0x8358a17eu},
+{0x13246f90u, 0xba136117u, 0x8dbd54d9u},
+{0xff800000u, 0xa2ab84a3u, 0x7f800000u},
+{0x5c842547u, 0x4981fe49u, 0x66863417u},
+{0x76348f2cu, 0xcd7c07b3u, 0xff800000u},
+{0x1a446617u, 0x1556a3f8u, 0x00000000u},
+{0xe60b31e5u, 0x1110c2a1u, 0xb79d6bc8u},
+{0x42146406u, 0x37318767u, 0x39cdcf49u},
+{0x5dc1d325u, 0x7579f997u, 0x7f800000u},
+{0xe6128c06u, 0x21219ac3u, 0xc7b9054fu},
+{0x751154d4u, 0xe50d185eu, 0xff800000u},
+{0x44b81d18u, 0x01fb4454u, 0x0734b5abu},
+{0xdb9c8d09u, 0x70d86877u, 0xff800000u},
+{0xf8c6a031u, 0xa2ced56fu, 0x5c207a81u},
+{0x32f5676au, 0xccd79bafu, 0xc04eaf17u},
+{0xe3a28f65u, 0x3d0e65eeu, 0xe134d887u},
+{0x3faf074fu, 0x8b303b21u, 0x8b70fae7u},
+{0xcce17c98u, 0x7e91c8e6u, 0xff800000u},
+{0x87a3750au, 0xd4afc420u, 0x1ce07478u},
+{0x0413b0cfu, 0x35baebe3u, 0x00000000u},
+{0xbb8d67eeu, 0xb1631569u, 0x2d7addf7u},
+{0xd499c2c7u, 0x99990b0fu, 0x2eb7d81bu},
+{0x0e366bb4u, 0x5bb5b406u, 0x2a817a6eu},
+{0x5bda0354u, 0xd50f86deu, 0xf174756du},
+{0x1dc6379au, 0x5eec61a7u, 0x3d3706deu},
+{0x664065b3u, 0xcb642471u, 0xf22b75f7u},
+{0x94407d5cu, 0x167f0832u, 0x80000000u},
+{0xb9b261d5u, 0xdd7ab004u, 0x57aeae30u},
+{0x81a83ea9u, 0x87eb3556u, 0x00000000u},
+{0x5987fb79u, 0x62e53844u, 0x7cf383adu},
+{0x75662e31u, 0xa826c751u, 0xde15f52bu},
+{0x408e0b25u, 0xa598ae8fu, 0xa6a96ef2u},
+{0x0820f517u, 0x26625bb2u, 0x00000000u},
+{0xe4554210u, 0xdde98d7du, 0x7f800000u},
+{0x95bd8c34u, 0xee722ce0u, 0x44b34fc3u},
+{0x152f59d6u, 0x6b0c28ceu, 0x40c00228u},
+{0x3c0bd9c3u, 0x6ed2df23u, 0x6b666510u},
+{0xa1b704d0u, 0x9ccb0449u, 0x00000000u},
+{0x29167178u, 0xf49bf8deu, 0xde3751e8u},
+{0xbb6d3bbeu, 0x6b102eeeu, 0xe7059d18u},
+{0x00de5449u, 0xf998fad5u, 0xbb04dbe3u},
+{0xbe51bc07u, 0x9f8851c5u, 0x1e5f5dc3u},
+{0x95d0f9f5u, 0x7d6b2ca4u, 0xd3bff9e5u},
+{0xa5e2fd6du, 0xd759095au, 0x3dc0711cu},
+{0x1092ce37u, 0x39334f75u, 0x0a4da782u},
+{0xdae685aau, 0x948babdau, 0x2ffb8aa6u},
+{0x42393b0bu, 0xbf5788c2u, 0xc21bf38au},
+{0x43a39805u, 0x10fa441eu, 0x151fedfcu},
+{0xa7929290u, 0xe4f8cf24u, 0x4d0e7495u},
+{0xf63b7eabu, 0x525ac506u, 0xff800000u},
+{0x1fa92001u, 0x9fb5ef4eu, 0x80000000u},
+{0xf8d2e0deu, 0xa0a9dad0u, 0x5a0beab1u},
+{0x9304e87du, 0xeec4ab17u, 0x424c35a6u},
+{0x0fc2e09bu, 0xe8e216dau, 0xb92c1baeu},
+{0xa13c38ecu, 0xc3313b9cu, 0x25024f2fu},
+{0x5ac82ca3u, 0x48a80f0au, 0x6403690du},
+{0x7a44192bu, 0x95cb0c3fu, 0xd09b8957u},
+{0x70942ae3u, 0xc8d144a1u, 0xf9f23d78u},
+{0xf1ea09f0u, 0x632d86d7u, 0xff800000u},
+{0x4800da20u, 0xdd62d41du, 0xe5e456a7u},
+{0x0d785aa6u, 0x2bdecf50u, 0x00000000u},
+{0x38cb93c1u, 0xf05423c0u, 0xe9a8b2cau},
+{0x52cf9c2au, 0x75da4526u, 0x7f800000u},
+{0x2766413du, 0x80d9ca05u, 0x80000000u},
+{0xd7e1d37au, 0xf2eb3c19u, 0x7f800000u},
+{0x51b65b44u, 0xc7d418e8u, 0xda171552u},
+{0xa4f884e5u, 0x59f9195du, 0xbf71d1e2u},
+{0xe3779018u, 0xd6ad0352u, 0x7aa74f96u},
+{0x56b90433u, 0x6375eb0du, 0x7ab1bae5u},
+{0x40b035f5u, 0x367b31fdu, 0x37ace750u},
+{0x8bfa4eccu, 0x31b8c7a4u, 0x80000000u},
+{0xfcc7acf9u, 0xfd19cda3u, 0x7f800000u},
+{0x7b9ba076u, 0x1d2960d3u, 0x594def95u},
+{0x13627eb2u, 0x7f586416u, 0x533f7373u},
+{0x92db39b6u, 0x3c0a9780u, 0x8f6d5db2u},
+{0x7980ad43u, 0x99927d5eu, 0xd39343a8u},
+{0x4d32b075u, 0x7f766c1eu, 0x7f800000u},
+{0xcd3cafdeu, 0x6f0a66c6u, 0xfccc051bu},
+{0xc835a4d7u, 0x6602f533u, 0xeeb9d760u},
+{0x379ea377u, 0x6ef8e1c9u, 0x671a3a46u},
+{0x7b33bc2bu, 0x09edacb5u, 0x45a6de75u},
+{0xd8dfaacfu, 0x16bcf3afu, 0xb0251658u},
+{0xbb21f15cu, 0xbd6ad2e1u, 0x39148c04u},
+{0x2099c0feu, 0x82517200u, 0x80000000u},
+{0xa404d4edu, 0xff6b8f56u, 0x63f473aau},
+{0xb2691b0bu, 0x1043c83du, 0x833245eeu},
+{0xb8463161u, 0xd153344au, 0x4a23832eu},
+{0x5ed14f9fu, 0x895cd7e1u, 0xa8b490eeu},
+{0x3a5554a9u, 0x414bdaa0u, 0x3c29e051u},
+{0x858816aau, 0x18a6ff3eu, 0x80000000u},
+{0x969f4670u, 0x54449a0du, 0xab74a38cu},
+{0xf2572705u, 0x28530f84u, 0xdb316233u},
+{0x2f18c41fu, 0x09a588bcu, 0x00000000u},
+{0x6536b63fu, 0xf51ef9a8u, 0xff800000u},
+{0x7f098977u, 0x99ca1b67u, 0xd9592a61u},
+{0x7a917520u, 0x74822e5cu, 0x7f800000u},
+{0xcf59b1a6u, 0xee20d141u, 0x7e08c0f9u},
+{0x683a9454u, 0x30d20e7au, 0x5999183au},
+{0x67cc30a0u, 0xa4b9438du, 0xcd13c505u},
+{0x04a7466du, 0x40c37e02u, 0x05ff79f6u},
+{0x17fceef2u, 0x7f800000u, 0x7f800000u},
+{0xe1ff961au, 0x82968c65u, 0x25164e1eu},
+{0x20cdabc5u, 0x813c18efu, 0x80000000u},
+{0x0af7e9e2u, 0xacd74339u, 0x80000000u},
+{0x128fe80du, 0xfa6e701eu, 0xcd8608c2u},
+{0x23dd4757u, 0x44e83cffu, 0x2948bd60u},
+{0x5d007ecdu, 0x12249f58u, 0x2fa5426du},
+{0x8006fa06u, 0x72960f9bu, 0x80000000u},
+{0x8eccbc84u, 0x53ed23a8u, 0xa33da70au},
+{0x77516f2cu, 0x871b0270u, 0xbefda09cu},
+{0x7ddb6c10u, 0x88626af0u, 0xc6c2110fu},
+{0xcfd6ab12u, 0x6a74cab3u, 0xfacd4506u},
+{0x01e4a162u, 0x34d1bef7u, 0x00000000u},
+{0xe1358d16u, 0x3cc032abu, 0xde884dbfu},
+{0x6703c00du, 0xcbc12e9fu, 0xf346d790u},
+{0xee14d0eau, 0xdd9b332au, 0x7f800000u},
+{0xc8636727u, 0x24c4f478u, 0xadaef423u},
+{0x9400b69fu, 0xb39a1d4fu, 0x081af930u},
+{0x92a09f76u, 0xaf0d2442u, 0x02311d28u},
+{0xfd4ee78au, 0x524d9104u, 0xff800000u},
+{0x1a32dae6u, 0x2eae2732u, 0x09735855u},
+{0x05f1260au, 0xde0cc933u, 0xa4849e54u},
+{0xd3025d2du, 0x60913f5fu, 0xf413ee18u},
+{0x24bc524fu, 0xd9831dc5u, 0xbec0e809u},
+{0x6d81c96bu, 0xd0cb61d3u, 0xfece38a0u},
+{0x68c707c3u, 0xea221649u, 0xff800000u},
+{0xea77eaacu, 0x4998c6dfu, 0xf493f3eeu},
+{0xc928d651u, 0x3f0cdeb1u, 0xc8b9d026u},
+{0xca1b784bu, 0xd2762a9fu, 0x5d157f7au},
+{0xf4104d1fu, 0xae39433eu, 0x62d0db45u},
+{0x75cfa5c3u, 0x7eeee2a3u, 0x7f800000u},
+{0x64333e8bu, 0x59540280u, 0x7e14718bu},
+{0xd59f709eu, 0x1159485bu, 0xa7875386u},
+{0x7c9d7b74u, 0xa52088bau, 0xe2458289u},
+{0xe029f2afu, 0x7c011f7au, 0xff800000u},
+{0xff800000u, 0x6689b5a1u, 0xff800000u},
+{0xbc0f739cu, 0xe5e106e6u, 0x627c30f3u},
+{0x33ecca2du, 0xc08a0e30u, 0xb4ff6437u},
+{0x0c6d796au, 0x401b22f9u, 0x0d0fe8f4u},
+{0xb63fda67u, 0x1f3e2279u, 0x960e7deeu},
+{0x7408e4f7u, 0x5bfa7d16u, 0x7f800000u},
+{0x70952b5bu, 0xc5cb9577u, 0xf6ed40f1u},
+{0x19c9dc2cu, 0xb628c8e5u, 0x908516e5u},
+{0x8af39343u, 0x2ae6420cu, 0x80000000u},
+{0x38aa9493u, 0x61a645d7u, 0x5add95c1u},
+{0x46a2a588u, 0x35268445u, 0x3c5396bfu},
+{0x59a41830u, 0x4a36ced8u, 0x646a5b90u},
+{0x960182fbu, 0xda8f2b15u, 0x3110dbecu},
+{0x9d519671u, 0x9abc613eu, 0x00000000u},
+{0x582aab94u, 0xb85c7512u, 0xd112f980u},
+{0x326026a5u, 0x8be473f2u, 0x80000000u},
+{0xe30dfae7u, 0xa7d7a151u, 0x4b6f2e5fu},
+{0x57780769u, 0xb4a8508eu, 0xcca312e9u},
+{0xa08f5785u, 0x3b909eecu, 0x9ca1f46eu},
+{0x241fc07cu, 0x5acc2b9du, 0x3f7ed134u},
+{0xe2352470u, 0xf29fae71u, 0x7f800000u},
+{0x773322d3u, 0xd102d545u, 0xff800000u},
+{0x66929d31u, 0x31f76096u, 0x590dacfbu},
+{0x6cd97ef7u, 0x2bb10cabu, 0x59166b8cu},
+{0xcd1737ecu, 0xcba5153fu, 0x59430730u},
+{0xa32c9b15u, 0xdd336540u, 0x40f1e968u},
+{0xac53fd1du, 0x0e769c08u, 0x80000000u},
+{0x2c201a4cu, 0x0d96b987u, 0x00000000u},
+{0x51c834b5u, 0x5925ff2eu, 0x6b81d189u},
+{0xf23be03bu, 0x0734de04u, 0xba04bc99u},
+{0xd150fd77u, 0x100639e1u, 0xa1db27d9u},
+{0x95847414u, 0x05e5d6b9u, 0x80000000u},
+{0xef71e973u, 0x21e48d97u, 0xd1d7f9b7u},
+{0x86bf94e9u, 0x25b30e7au, 0x80000000u},
+{0x04b1a2eau, 0xaf39c793u, 0x80000000u},
+{0xe14553a4u, 0x778025ccu, 0xff800000u},
+{0x65e19b99u, 0x357ef874u, 0x5be0b357u},
+{0xd8e3766du, 0x3931f260u, 0xd29e1c3du},
+{0x4d1582d4u, 0x5810ceb3u, 0x65a9249eu},
+{0xd0926a1fu, 0x1a009fdau, 0xab1320f8u},
+{0x0a6e0a66u, 0x72f79857u, 0x3de639afu},
+{0xc2ca8a71u, 0x35c9743fu, 0xb91f62abu},
+{0xbf666134u, 0xa60ed057u, 0x26008568u},
+{0xfef641a2u, 0xb67a461fu, 0x75f0bf8cu},
+{0xa480af6du, 0x59a9d83au, 0xbeaac100u},
+{0xd21e440fu, 0xc5562d5fu, 0x580468f1u},
+{0xbf8940b4u, 0xe6228331u, 0x662e4291u},
+{0xe927ef3au, 0x95dbcaf9u, 0x3f902ecdu},
+{0x427bd98au, 0xa6bfd2fcu, 0xa9bcb6deu},
+{0x6b8ae283u, 0x6b07cdb7u, 0x7f800000u},
+{0xae259d46u, 0x0f42914cu, 0x80000000u},
+{0x108ea71cu, 0x4c98b402u, 0x1daa2f0eu},
+{0x47526bfcu, 0x2aff6271u, 0x32d1ea7au},
+{0xb085879cu, 0x6c2f0dceu, 0xdd369dceu},
+{0x9ad5cf97u, 0x18f2fcfcu, 0x80000000u},
+{0xfa115742u, 0x98969070u, 0x532af643u},
+{0x56970281u, 0xbf289e8cu, 0xd646ee56u},
+{0x9407c090u, 0xa5559116u, 0x00000000u},
+{0x0c5e5c48u, 0xc93e3d42u, 0x96253db3u},
+{0xde69a0ccu, 0x97aa3467u, 0x369b549au},
+{0x5b95aa4du, 0x36df19cdu, 0x53026e6fu},
+{0xcb98c0cau, 0x846205e0u, 0x1086ddb4u},
+{0x8dd13af1u, 0x76fc0720u, 0xc54dfbd8u},
+{0xea5f0845u, 0x9704c19fu, 0x41e751e7u},
+{0xff800000u, 0x1aac6ba1u, 0xff800000u},
+{0x4e0f44feu, 0x3be2434fu, 0x4a7d4127u},
+{0x88ee57e4u, 0x7df0ddd8u, 0xc76040f1u},
+{0xf0d7631eu, 0xc937641eu, 0x7a9a4c16u},
+{0x34d08309u, 0xac6833c5u, 0xa1bd20ebu},
+{0xc5a87813u, 0xa2f25ae2u, 0x291f7d51u},
+{0xbf4e6c85u, 0x030f3f1cu, 0x82e70303u},
+{0x91dd6bcdu, 0x25aea118u, 0x80000000u},
+{0x07e75c4eu, 0xe7c8c7f3u, 0xb03574d1u},
+{0x70caf24bu, 0x90e7e3fau, 0xc237d55du},
+{0x5321dfa0u, 0xd6e9a07du, 0xea93ba03u},
+{0xa88ec5a6u, 0xac4156bbu, 0x1557a6c2u},
+{0x43021ba5u, 0x80f10da0u, 0x847505e6u},
+{0xcc340c2eu, 0x306cae4eu, 0xbd2675d2u},
+{0x6dc3cabcu, 0x3afaf063u, 0x693febd5u},
+{0x2ec4e90bu, 0xa40a3223u, 0x93549861u},
+{0x3225f648u, 0xb6648f16u, 0xa9142c1bu},
+{0xca47525fu, 0x176ded7au, 0xa2394028u},
+{0xe6d711ccu, 0x68b07ec0u, 0xff800000u},
+{0x04e49851u, 0x8af76a57u, 0x80000000u},
+{0x0e158411u, 0xe2a8faedu, 0xb1456271u},
+{0x4645574eu, 0x27c592abu, 0x2e984d3fu},
+{0x626e2802u, 0x3fa4214fu, 0x6298b09eu},
+{0x1372e532u, 0xe7dfe914u, 0xbbd472ccu},
+{0xfe1bafe0u, 0xbfe5507bu, 0x7e8b7545u},
+{0xadd17863u, 0x5afecd28u, 0xc9507d50u},
+{0x5569ea47u, 0x4571b0feu, 0x5b5cd746u},
+{0xc963b477u, 0x7b5f95e2u, 0xff800000u},
+{0x3de1ff85u, 0x2b2031b4u, 0x298d6b94u},
+{0xed2add10u, 0xca1b9b58u, 0x77cfb70fu},
+{0x3199488fu, 0x50612b90u, 0x4286d2dbu},
+{0x22ef79f3u, 0xc9a10bc7u, 0xad16a6b6u},
+{0xfde354c4u, 0x5d288ae7u, 0xff800000u},
+{0xac3dbfe1u, 0x7679deedu, 0xe33934deu},
+{0x7de270b8u, 0x9d0286adu, 0xdb66e8bbu},
+{0x52096fd5u, 0xccf17aa0u, 0xdf81a41du},
+{0xe9da623eu, 0x7124268au, 0xff800000u},
+{0x7258778fu, 0x051f1c95u, 0x38068a6du},
+{0xe79b3c26u, 0xedc27b4bu, 0x7f800000u},
+{0x1bbc6349u, 0xf0498791u, 0xcc944db7u},
+{0xeb779179u, 0x260fbcacu, 0xd20b00b8u},
+{0x6e32b3a2u, 0x23554228u, 0x5214dda4u},
+{0x7f800000u, 0x55bcc2aeu, 0x7f800000u},
+{0x1b94a68fu, 0x720e7e80u, 0x4e257bafu},
+{0x4976b875u, 0x40ed589du, 0x4ae4be2bu},
+{0x8edda7ffu, 0x0ae45fadu, 0x80000000u},
+{0x06cb25f4u, 0xb0459d5fu, 0x80000000u},
+{0x07d389edu, 0xa57031b8u, 0x80000000u},
+{0x059d1993u, 0xe1adc72fu, 0xa7d54908u},
+{0x7a3e9d6cu, 0x3a8f512cu, 0x75556cc0u},
+{0x5dc10191u, 0xf78bc6c8u, 0xff800000u},
+{0x3cd0de92u, 0x9d6a7a07u, 0x9abf4f01u},
+{0xe46c7aabu, 0x2ffdae7cu, 0xd4ea5669u},
+{0x7711cd20u, 0x462fb683u, 0x7dc82657u},
+{0x39a61b3cu, 0x0c10c8e4u, 0x063be356u},
+{0x054c9477u, 0x942c49e9u, 0x80000000u},
+{0x688c3b7au, 0x7182fcadu, 0x7f800000u},
+{0xdd0c9ba4u, 0xa6a43aa5u, 0x443467d6u},
+{0x6e8c67acu, 0xa1b45cc4u, 0xd0c5d78bu},
+{0xe51de0c0u, 0x555475f1u, 0xfb0306dbu},
+{0x298e70cbu, 0x1e17e88eu, 0x08290bdau},
+{0xe59a0deeu, 0x7736d8c5u, 0xff800000u},
+{0xe9903f24u, 0x6fc43ac5u, 0xff800000u},
+{0x5cbcec1au, 0x92a6a5e3u, 0xaff5f709u},
+{0xf29f9605u, 0x8ba91fcfu, 0x3ed2dbbbu},
+{0x2c1a56b6u, 0x163ff868u, 0x02e778e9u},
+{0x2c22a0bbu, 0x138501b8u, 0x00000000u},
+{0xb664c7f2u, 0xb290b2d3u, 0x29815048u},
+{0xc2f36ffeu, 0xaf4daed0u, 0x32c396eau},
+{0xcef558a5u, 0x7e7793a8u, 0xff800000u},
+{0x21a2ff7cu, 0x15f2e845u, 0x00000000u},
+{0x06d17c3au, 0xdd9be90du, 0xa4ff29d8u},
+{0x493d42ffu, 0x4d2c6e85u, 0x56fef571u},
+{0xb01c766eu, 0x77ae5dfcu, 0xe85523e0u},
+{0xeaf339f1u, 0x7358cbfeu, 0xff800000u},
+{0xb577e808u, 0x9ca26b00u, 0x129d4873u},
+{0xdf946a54u, 0x9926c1bcu, 0x39415a87u},
+{0xd516ccbbu, 0x51065514u, 0xe69e428fu},
+{0xd866bacbu, 0x20ce0548u, 0xb9b9af12u},
+{0xc18ba4d3u, 0x0a087aeau, 0x8c14e539u},
+{0x86ae6121u, 0xcb4fc5acu, 0x128d8730u},
+{0x5379f624u, 0x7037d344u, 0x7f800000u},
+{0x1ba66126u, 0x429b4b7au, 0x1ec9dbc0u},
+{0x4befa31fu, 0xdf9aa376u, 0xec10c124u},
+{0xa9c3f1efu, 0x11f14ef7u, 0x80000000u},
+{0xa3e97c6au, 0xaa6a7a34u, 0x0ed5db2eu},
+{0x74a018ecu, 0x7bccd2c4u, 0x7f800000u},
+{0x41b126d3u, 0x87b1f82cu, 0x89f64f28u},
+{0x7608086eu, 0xb3edae22u, 0xea7c98abu},
+{0xb9cc63f2u, 0x226925a4u, 0x9cba2505u},
+{0xebabdcccu, 0xfd86a0e9u, 0x7f800000u},
+{0x48f1e14bu, 0xc8216d7du, 0xd1988623u},
+{0x65dda831u, 0x958affd8u, 0xbbf0b460u},
+{0xa39a9130u, 0x28268cefu, 0x8c491e7au},
+{0x0ba4643bu, 0xf0a04698u, 0xbccdd7f4u},
+{0x903371eau, 0x41ec45ddu, 0x92a59dfcu},
+{0xeae86bdbu, 0x0d28ba9cu, 0xb8993034u},
+{0x82252fc6u, 0x421cfb28u, 0x84ca9659u},
+{0x74ddead7u, 0xdc7dbca8u, 0xff800000u},
+{0x8c5896c9u, 0xa9830eefu, 0x00000000u},
+{0xcbece1a5u, 0x9a6ab1fbu, 0x26d92af1u},
+{0x2b10ce59u, 0xbb351011u, 0xa6ccd5f7u},
+{0x6cf85c3cu, 0x8cb8bf6bu, 0xba333c00u},
+{0xfce39111u, 0xdda915bcu, 0x7f800000u},
+{0xb227c9ccu, 0x8414a483u, 0x00000000u},
+{0xebb4a4c1u, 0x852d2914u, 0x317460a6u},
+{0x1df4241du, 0x1b1637a3u, 0x00000000u},
+{0x5d5dff0bu, 0xd458996fu, 0xf23bd43fu},
+{0x82ed29b6u, 0x02b77c13u, 0x80000000u},
+{0x3e01102cu, 0xc7cf2de8u, 0xc650e671u},
+{0xb6ad3b79u, 0xab1e8831u, 0x22568dbbu},
+{0x288e0513u, 0x1a969eddu, 0x03a71e36u},
+{0xcc490562u, 0xd1830ee3u, 0x5e4dd2e3u},
+{0x7f13e094u, 0xb4714c76u, 0xf40b6296u},
+{0xb2a8e4e0u, 0xf7e86a90u, 0x6b1955b9u},
+{0x44b3dbbbu, 0x10c6981fu, 0x160b86d3u},
+{0x079538aeu, 0xbb8d0c84u, 0x83a46f07u},
+{0x94d72899u, 0x5395f837u, 0xa8fc167du},
+{0x9dd64434u, 0xe888bdfdu, 0x46e4e67fu},
+{0xc54585eau, 0x633301f3u, 0xe90a1e24u},
+{0x8d9b35ddu, 0xed45db63u, 0x3b6feaecu},
+{0x1f436f86u, 0xbbba0ef4u, 0x9b8e0a72u},
+{0x553bbe73u, 0x5cceaaaeu, 0x7297906du},
+{0x03561a32u, 0x26e1bdecu, 0x00000000u},
+{0x0b306025u, 0x3844f0b3u, 0x0407af72u},
+{0x4ccbe104u, 0x2c5fc60fu, 0x39b236beu},
+{0x8c574810u, 0x75ea8110u, 0xc2c53467u},
+{0xc71a5ac5u, 0x03615877u, 0x8b07df1eu},
+{0x30cfdfa0u, 0x7f03ba12u, 0x7055ed0cu},
+{0xf09302fbu, 0xaa0cbeaau, 0x5b21a63eu},
+{0x356540bdu, 0xaba10298u, 0xa1903009u},
+{0xa06f88fau, 0x52293906u, 0xb31e56c8u},
+{0xd9da1119u, 0xe7f54e96u, 0x7f800000u},
+{0x53e71722u, 0x3b125256u, 0x4f841584u},
+{0x1284f080u, 0xe69d4697u, 0xb9a3584du},
+{0x6616160fu, 0x3a3277fcu, 0x60d1435du},
+{0xdb0f0c78u, 0x79e4af79u, 0xff800000u},
+{0xd032db73u, 0x87ac5842u, 0x1870d236u},
+{0x3b073e03u, 0x872cb8f1u, 0x82b67ebcu},
+{0x421dc30du, 0x9c179c0bu, 0x9ebadc6du},
+{0x5b9ea312u, 0x9d2f18cau, 0xb95901acu},
+{0x01f19609u, 0x24043a9au, 0x00000000u},
+{0xe5aa8fe8u, 0xe46be50bu, 0x7f800000u},
+{0x77caee1fu, 0x8a5afe49u, 0xc2ad9859u},
+{0x96f3516du, 0x08f96d45u, 0x80000000u},
+{0x15103c0du, 0x3b21942eu, 0x10b61282u},
+{0x2e32d684u, 0x8bf94aecu, 0x80000000u},
+{0x1703faaeu, 0xa46de2ebu, 0x80000000u},
+{0x6f539d4cu, 0xf85c2e7du, 0xff800000u},
+{0xf76dd30du, 0x2752faf7u, 0xdf440046u},
+{0x76ca022au, 0xbc1b3f9eu, 0xf3750305u},
+{0xa40de08au, 0xdeacc6ddu, 0x433f8226u},
+{0xa4bde0c2u, 0xdd7ac73au, 0x42ba0142u},
+{0xabb1ede6u, 0x5c7f6403u, 0xc8b1817bu},
+{0xa8736e06u, 0x0f1e105cu, 0x80000000u},
+{0xf0af00e5u, 0xd243c2bfu, 0x7f800000u},
+{0x4a246fb6u, 0x4e8bbadbu, 0x5933815bu},
+{0x617207b2u, 0xde157b97u, 0xff800000u},
+{0xeb5e866bu, 0x97c3fdb0u, 0x43aa5ce7u},
+{0x802fdb74u, 0x8b4a4d49u, 0x00000000u},
+{0x66a9afd5u, 0xd56b948cu, 0xfc9c26dfu},
+{0x7f343474u, 0xd31979adu, 0xff800000u},
+{0xf56c99b7u, 0x07f3c717u, 0xbde14de9u},
+{0x549a38a8u, 0xd5740235u, 0xea92ff54u},
+{0x30eefa0eu, 0x7ecf6004u, 0x704195d3u},
+{0xdb8e2d22u, 0xb28ba59du, 0x4e9b1cf7u},
+{0xd2acc74eu, 0xc6a795b5u, 0x59e2361cu},
+{0x56e33d55u, 0x9bb4a554u, 0xb32059e1u},
+{0x178f5ca5u, 0xc7876343u, 0x9f97a2e3u},
+{0xdf27f686u, 0xdf5d861au, 0x7f1157ceu},
+{0x29783a9eu, 0x18487e7au, 0x0242686fu},
+{0x13d0b8deu, 0x172e4c06u, 0x00000000u},
+{0x8f96d6e7u, 0xa4da01a1u, 0x00000000u},
+{0x21f587f0u, 0xfa6d61edu, 0xdce3acc5u},
+{0xb0c53b67u, 0xe079983cu, 0x51c04c11u},
+{0x8291fc69u, 0x96a8b3cau, 0x00000000u},
+{0x7178692eu, 0xabeb1944u, 0xdde42111u},
+{0x8d5e0fb0u, 0xb46cc786u, 0x024d6389u},
+{0x062728b7u, 0x48458029u, 0x0f00f604u},
+{0x93dd24a0u, 0xae13e132u, 0x027f7d21u},
+{0xf322d177u, 0x3270123au, 0xe618aff7u},
+{0x7aabe467u, 0xfe14cadbu, 0xff800000u},
+{0x55e75d3au, 0x378ebe31u, 0x4e01019au},
+{0x2d41ee14u, 0xf9dea0cfu, 0xe7a8a647u},
+{0x2d0f107du, 0x6dccd2cdu, 0x5b64ede3u},
+{0xb7152088u, 0xafb294acu, 0x27500e73u},
+{0x777c446bu, 0xfcf9c568u, 0xff800000u},
+{0xc20764cfu, 0x4722cbe3u, 0xc9ac3340u},
+{0x2ef49dfcu, 0xe13afd67u, 0xd0b2acecu},
+{0x069b874bu, 0xb9366a1eu, 0x80000000u},
+{0x043fbc42u, 0x2ec14f4au, 0x00000000u},
+{0x8e57edc3u, 0xcb3171d7u, 0x1a15ab69u},
+{0x99ea59e0u, 0xfa5ce871u, 0x54ca3a05u},
+{0x4098e209u, 0x5820ad3du, 0x593fe976u},
+{0x5c1589beu, 0x807b8d27u, 0x80000000u},
+{0x4460df73u, 0x557003a1u, 0x5a52d4acu},
+{0x710db01bu, 0xe7ae041fu, 0xff800000u},
+{0xc942b05du, 0x8b6e76dfu, 0x15355a5du},
+{0xad910816u, 0x0ae20d58u, 0x80000000u},
+{0x3b7809a8u, 0x90921b3du, 0x8c8d8fe6u},
+{0x91cfc455u, 0x120852c7u, 0x80000000u},
+{0xfde4eef2u, 0x227575b2u, 0xe0db81eeu},
+{0x37bf6380u, 0x4cb96338u, 0x450a9915u},
+{0x05f1fc28u, 0x181cb3edu, 0x00000000u},
+{0x76b3f3edu, 0x942836c5u, 0xcb6c7d27u},
+{0xb6a50692u, 0xeb0ad06eu, 0x6232f7ceu},
+{0x6e216effu, 0x61eeb64du, 0x7f800000u},
+{0x3c1f2566u, 0xb917787bu, 0xb5bc53eau},
+{0x89ab5550u, 0x5c05b7e4u, 0xa632fccau},
+{0xaa585ccdu, 0xa1b700d9u, 0x0c9aab0eu},
+{0x4f1132d1u, 0x3d1a0f5fu, 0x4caec293u},
+{0xde0a5db9u, 0xa0d7e5fau, 0x3f696207u},
+{0xcd4b0274u, 0x8ac16583u, 0x18995d59u},
+{0xd645515fu, 0xb519e127u, 0x4bed3659u},
+{0x98676ebeu, 0xb27decd6u, 0x0b658e8du},
+{0x5487d91au, 0x3170321bu, 0x467eec3eu},
+{0xcf9dfb90u, 0x97a5a0c7u, 0x27cc6cb8u},
+{0x8a22ce3du, 0xbb6bec62u, 0x061609a6u},
+{0x40f36cdfu, 0xfe6e5656u, 0xff800000u},
+{0x4b379b31u, 0x2f27bcc5u, 0x3af09b40u},
+{0x26ff4c1cu, 0xe8b606c2u, 0xd03586d9u},
+{0x0d5b5c2cu, 0x4b1b095au, 0x1904d8d2u},
+{0xef6bc353u, 0x7e00a9aeu, 0xff800000u},
+{0x4d8a56bdu, 0xb2822dbau, 0xc08cb183u},
+{0xe6bcdf53u, 0xdb2ac4deu, 0x7f800000u},
+{0xbd09dd39u, 0xb71c0a4eu, 0x34a810b7u},
+{0x25a3177au, 0x88c376e7u, 0x80000000u},
+{0x24bc15a2u, 0x6dec97d5u, 0x532dd37fu},
+{0x4ee5e1f9u, 0x3dca736au, 0x4d35cbf2u},
+{0x1aa4a508u, 0xbbacdc60u, 0x96de593au},
+{0x8916f0fbu, 0x87403ad0u, 0x00000000u},
+{0xfb532aafu, 0x4ff51262u, 0xff800000u},
+{0x6ee6c6a3u, 0x6b11330cu, 0x7f800000u},
+{0x4e331b8fu, 0x61f0a4f1u, 0x70a85d3cu},
+{0x1e5d484bu, 0x0aa3294au, 0x00000000u},
+{0x0a481317u, 0xe56ec717u, 0xb03a9d58u},
+{0x9dc884a8u, 0xd91db347u, 0x37770b8fu},
+{0xbc62f251u, 0x1f5e7207u, 0x9c453338u},
+{0x837e46cau, 0x3d6ff965u, 0x816e5bceu},
+{0xc6bc45ebu, 0x22bbc0ecu, 0xaa0a14f5u},
+{0xb7e9efefu, 0x4aeb7053u, 0xc35725e5u},
+{0x5a530f33u, 0xca96bcbau, 0xe5788d01u},
+{0x776c5e45u, 0x8a5b0a0cu, 0xc24a3decu},
+{0x4dde3d57u, 0x603b2bb3u, 0x6ea27cbeu},
+{0x03795d65u, 0x90ffbf52u, 0x80000000u},
+{0x0265f131u, 0x7f800000u, 0x7f800000u},
+{0x132d2f7cu, 0xeb323722u, 0xbef120a1u},
+{0xc0afba17u, 0x2b7b143cu, 0xacac5958u},
+{0x997e8180u, 0xe57aecd5u, 0x3f7975eau},
+{0xe0086689u, 0x2cf8a888u, 0xcd847d20u},
+{0x27346cefu, 0x6e36f2c2u, 0x5600f08au},
+{0x81d30002u, 0x0334b70au, 0x80000000u},
+{0xf85466a2u, 0x3022d002u, 0xe9071588u},
+{0xe253555du, 0xa60fa340u, 0x48ed26e6u},
+{0x5128f5b8u, 0xe3574534u, 0xf50e140au},
+{0x1323195fu, 0x2f793fcau, 0x031ecc51u},
+{0x137b0c72u, 0xe5203df9u, 0xb91d248du},
+{0x171622fau, 0x78f211e8u, 0x508df791u},
+{0x353f99ecu, 0xebd1d0f6u, 0xe19d090fu},
+{0x8c190029u, 0x1a16dc7au, 0x80000000u},
+{0x1bc901b6u, 0xa7ce3fe8u, 0x8421f18eu},
+{0x7538e7c7u, 0xc154f89cu, 0xf719d382u},
+{0xd88439a9u, 0x7f800000u, 0xff800000u},
+{0xf807c86fu, 0x64332c2du, 0xff800000u},
+{0x0d069a37u, 0xf4bcd2c4u, 0xc2469024u},
+{0x5b228456u, 0x2461e3a9u, 0x400f66d6u},
+{0xf7ea8fc6u, 0x750ba2fau, 0xff800000u},
+{0xe983653au, 0xb6d81bccu, 0x60ddd75bu},
+{0x7d23c7b8u, 0x972f981bu, 0xd4e0adadu},
+{0x5c7cd175u, 0xc2e89647u, 0xdfe5b23bu},
+{0x23a17884u, 0x7b122c15u, 0x5f386512u},
+{0xb39b8ba2u, 0xc712e083u, 0x3b327c18u},
+{0x40255382u, 0xc90238a9u, 0xc9a831ffu},
+{0x5bb3f219u, 0x36bcba8eu, 0x5304a8ecu},
+{0x59c1ee8au, 0x1bc4611cu, 0x3614c432u},
+{0x6d3963bdu, 0xbbc262f9u, 0xe98cc542u},
+{0xd34b1140u, 0xaa657972u, 0x3e3606c4u},
+{0x795c6228u, 0x9c0b382du, 0xd5efb350u},
+{0xf09df3e1u, 0x45960f6cu, 0xf6b92cd4u},
+{0xf6977096u, 0xe49abc78u, 0x7f800000u},
+{0x2109367au, 0x0cc85ea1u, 0x00000000u},
+{0xb5d4e11fu, 0x4ae99c90u, 0xc1424316u},
+{0x63c2db9eu, 0x41db5e2cu, 0x6626f98eu},
+{0x62d953ffu, 0xf75229d6u, 0xff800000u},
+{0x8204d810u, 0x1ee2fd7eu, 0x80000000u},
+{0x482c5c08u, 0x7a7f3625u, 0x7f800000u},
+{0x7e81429bu, 0x685db0c6u, 0x7f800000u},
+{0x4a7106f4u, 0x353042adu, 0x4025f38eu},
+{0x5db1b2bcu, 0xf32164cdu, 0xff800000u},
+{0xf61e6777u, 0x39f57fe2u, 0xf097e826u},
+{0x3a168e3au, 0xfa8d12d1u, 0xf525eeceu},
+{0x7f681678u, 0x0fb87ec1u, 0x4fa74310u},
+{0x2c8b126eu, 0x4c4c30a2u, 0x395dda36u},
+{0x1cf4633fu, 0x34c12887u, 0x12386583u},
+{0x18741a48u, 0x03e26ca5u, 0x00000000u},
+{0xa2412606u, 0x5a629471u, 0xbd2af391u},
+{0x1e961674u, 0x6c5dad58u, 0x4b81f703u},
+{0xb430b6dcu, 0xed774f63u, 0x622ab73bu},
+{0x24c9da46u, 0x6fcda227u, 0x552223a5u},
+{0x2f1aa222u, 0x86039bcau, 0x80000000u},
+{0xec1cdd4bu, 0x9422a1adu, 0x40c74e35u},
+{0xbdb9a3a0u, 0x67f8c966u, 0xe634688eu},
+{0x73dffa00u, 0x98e66872u, 0xcd4995fdu},
+{0xa1ff4e21u, 0x43583386u, 0xa5d79d4eu},
+{0x160f7415u, 0x54ed4360u, 0x2b84f439u},
+{0xc8379075u, 0x8dacda32u, 0x1677e307u},
+{0x9aaca607u, 0x6063e2deu, 0xbb99b038u},
+{0x89515730u, 0x7c97d273u, 0xc6784d0au},
+{0x068cd2b0u, 0xa9244fe2u, 0x80000000u},
+{0xefddb149u, 0x01052115u, 0xb1669382u},
+{0x79ea5092u, 0x6c9530b4u, 0x7f800000u},
+{0x7c2186b4u, 0xc92469f1u, 0xff800000u},
diff --git a/test/pico_sha256_test/pico_sha256_test.c b/test/pico_sha256_test/pico_sha256_test.c
index 21e748c2f..5b38d15c5 100644
--- a/test/pico_sha256_test/pico_sha256_test.c
+++ b/test/pico_sha256_test/pico_sha256_test.c
@@ -6,6 +6,9 @@
#include
#include
+// Include sys/types.h before inttypes.h to work around issue with
+// certain versions of GCC and newlib which causes omission of PRIu64
+#include
#include
#include
diff --git a/test/pico_stdlib_test/pico_stdlib_test.c b/test/pico_stdlib_test/pico_stdlib_test.c
index ef955c186..11f1f7900 100644
--- a/test/pico_stdlib_test/pico_stdlib_test.c
+++ b/test/pico_stdlib_test/pico_stdlib_test.c
@@ -5,6 +5,9 @@
*/
#include
+// Include sys/types.h before inttypes.h to work around issue with
+// certain versions of GCC and newlib which causes omission of PRIu64
+#include
#include
#include "pico/stdlib.h"
#include "pico/bit_ops.h"
diff --git a/test/pico_time_test/pico_time_test.c b/test/pico_time_test/pico_time_test.c
index 987b03f20..362187ddb 100644
--- a/test/pico_time_test/pico_time_test.c
+++ b/test/pico_time_test/pico_time_test.c
@@ -10,6 +10,9 @@
#include
#include "pico/stdlib.h"
#include "pico/test.h"
+// Include sys/types.h before inttypes.h to work around issue with
+// certain versions of GCC and newlib which causes omission of PRIi64
+#include
#include
PICOTEST_MODULE_NAME("pico_time_test", "pico_time test harness");
@@ -69,6 +72,8 @@ static bool repeating_timer_callback(struct repeating_timer *t) {
#endif
int issue_195_test(void);
+int issue_1812_test(void);
+int issue_1953_test(void);
int main() {
setup_default_uart();
@@ -189,13 +194,19 @@ int main() {
PICOTEST_END_SECTION();
+
PICOTEST_START_SECTION("Repeating timertest");
for(uint i=0;i= 6us (PICO_TIME_SLEEP_OVERHEAD_ADJUST_US)
+ absolute_time_t timeout = make_timeout_time_ms(3000);
+ while(absolute_time_diff_us(get_absolute_time(), timeout) > 0) {
+ sleep_us(5);
+ }
+
uint callbacks = 0;
for(uint i=0;i str:
"""Return the path to bazelisk or bazel."""
if shutil.which("bazelisk"):
- return "bazelisk"
+ return shutil.which("bazelisk")
if shutil.which("bazel"):
return "bazel"
@@ -93,12 +97,16 @@ def run_bazel(args, check=False, **kwargs):
return proc
+def print_to_stderr(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
def print_framed_string(s):
"""Frames a string of text and prints it to highlight script steps."""
header_spacer = "#" * (len(s) + 12)
- print(header_spacer)
- print("### " + s + " ###")
- print(header_spacer)
+ print_to_stderr(header_spacer)
+ print_to_stderr("### " + s + " ###")
+ print_to_stderr(header_spacer)
def setup_logging():
diff --git a/tools/check_board_header.py b/tools/check_board_header.py
index 617f3940b..c259c8131 100755
--- a/tools/check_board_header.py
+++ b/tools/check_board_header.py
@@ -23,41 +23,184 @@
# warnings off by default, because some boards use the same pin for multiple purposes
show_warnings = False
-interfaces_json = "src/rp2040/rp2040_interface_pins.json"
-if not os.path.isfile(interfaces_json):
- raise Exception("{} doesn't exist".format(interfaces_json))
+chip_interfaces = {
+ 'RP2040': "src/rp2040/rp2040_interface_pins.json",
+ 'RP2350A': "src/rp2350/rp2350a_interface_pins.json",
+ 'RP2350B': "src/rp2350/rp2350b_interface_pins.json",
+}
+
+compulsory_cmake_settings = set(['PICO_PLATFORM'])
+compulsory_cmake_default_settings = set(['PICO_FLASH_SIZE_BYTES'])
+matching_cmake_default_settings = set(['PICO_FLASH_SIZE_BYTES', 'PICO_RP2350_A2_SUPPORTED'])
+compulsory_defines = set(['PICO_FLASH_SIZE_BYTES'])
+
+DefineType = namedtuple("DefineType", ["name", "value", "resolved_value", "lineno"])
+
+def list_to_string_with(lst, joiner):
+ elems = len(lst)
+ if elems == 0:
+ return ""
+ elif elems == 1:
+ return str(lst[0])
+ else:
+ return "{} {} {}".format(", ".join(str(l) for l in lst[:-1]), joiner, lst[-1])
+
board_header = sys.argv[1]
if not os.path.isfile(board_header):
raise Exception("{} doesn't exist".format(board_header))
+board_header_basename = os.path.basename(board_header)
-with open(interfaces_json) as interfaces_fh:
- interface_pins = json.load(interfaces_fh)
- allowed_interfaces = interface_pins["interfaces"]
- allowed_pins = set(interface_pins["pins"])
- # convert instance-keys to integers (allowed by Python but not by JSON)
- for interface in allowed_interfaces:
- instances = allowed_interfaces[interface]["instances"]
- # can't modify a list that we're iterating over, so iterate over a copy
- instances_copy = list(instances)
- for instance in instances_copy:
- instance_num = int(instance)
- instances[instance_num] = instances.pop(instance)
-
-DefineType = namedtuple("DefineType", ["name", "value", "resolved_value", "lineno"])
+expected_include_suggestion = "/".join(board_header.split("/")[-2:])
+expected_include_guard = "_" + re.sub(r"\W", "_", expected_include_suggestion.upper())
+expected_board_detection = re.sub(r"\W", "_", expected_include_suggestion.split("/")[-1].upper()[:-2])
defines = dict()
-pins = dict() # dict of lists
+cmake_settings = dict()
+cmake_default_settings = dict()
+
has_include_guard = False
has_board_detection = False
has_include_suggestion = False
-expected_include_suggestion = "/".join(board_header.split("/")[-2:])
-expected_include_guard = "_" + re.sub(r"\W", "_", expected_include_suggestion.upper())
-expected_board_detection = re.sub(r"\W", "_", expected_include_suggestion.split("/")[-1].upper()[:-2])
+
+
+def read_defines_from(header_file, defines_dict):
+ with open(header_file) as fh:
+ last_ifndef = None
+ last_ifndef_lineno = -1
+ validity_stack = [True]
+ board_detection_is_next = False
+ for lineno, line in enumerate(fh.readlines()):
+ lineno += 1
+ # strip trailing comments
+ line = re.sub(r"(?<=\S)\s*//.*$", "", line)
+
+ # look for "// pico_cmake_set BLAH_BLAH=42"
+ m = re.match(r"^\s*//\s*pico_cmake_set\s+(\w+)\s*=\s*(.+?)\s*$", line)
+ if m:
+ #print(m.groups())
+ name = m.group(1)
+ value = m.group(2)
+ # check all uppercase
+ if name != name.upper():
+ raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
+ # check for multiply-defined values
+ if name in cmake_settings:
+ if cmake_settings[name].value != value:
+ raise Exception("{}:{} Conflicting values for pico_cmake_set {} ({} and {})".format(board_header, lineno, name, cmake_settings[name].value, value))
+ else:
+ if show_warnings:
+ warnings.warn("{}:{} Multiple values for pico_cmake_set {} ({} and {})".format(board_header, lineno, name, cmake_settings[name].value, value))
+ else:
+ cmake_settings[name] = DefineType(name, value, None, lineno)
+ continue
+
+ # look for "// pico_cmake_set_default BLAH_BLAH=42"
+ m = re.match(r"^\s*//\s*pico_cmake_set_default\s+(\w+)\s*=\s*(.+?)\s*$", line)
+ if m:
+ #print(m.groups())
+ name = m.group(1)
+ value = m.group(2)
+ # check all uppercase
+ if name != name.upper():
+ raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
+ if name not in cmake_default_settings:
+ cmake_default_settings[name] = DefineType(name, value, None, lineno)
+ continue
+
+ # look for "#else"
+ m = re.match(r"^\s*#else\s*$", line)
+ if m:
+ validity_stack[-1] = not validity_stack[-1]
+ continue
+
+ # look for #endif
+ m = re.match(r"^\s*#endif\s*$", line)
+ if m:
+ validity_stack.pop()
+ continue
+
+ if validity_stack[-1]:
+ # look for "#include "foo.h"
+ m = re.match(r"""^\s*#include\s+"(.+?)"\s*$""", line)
+ if m:
+ include = m.group(1)
+ #print("Found nested include \"{}\" in {}".format(include, header_file))
+ assert include.endswith(".h")
+ # assume that the include is also in the boards directory
+ assert "/" not in include or include.startswith("boards/")
+ read_defines_from(os.path.join(os.path.dirname(board_header), os.path.basename(include)), defines)
+ continue
+
+ # look for "#if BLAH_BLAH"
+ m = re.match(r"^\s*#if\s+(\w+)\s*$", line)
+ if m:
+ last_if = m.group(1)
+ last_if_lineno = lineno
+ validity_stack.append(bool(defines[last_if].resolved_value))
+ continue
+
+ # look for "#ifdef BLAH_BLAH"
+ m = re.match(r"^\s*#ifdef\s+(\w+)\s*$", line)
+ if m:
+ last_ifdef = m.group(1)
+ last_ifdef_lineno = lineno
+ validity_stack.append(last_ifdef in defines)
+ continue
+
+ # look for "#ifndef BLAH_BLAH"
+ m = re.match(r"^\s*#ifndef\s+(\w+)\s*$", line)
+ if m:
+ last_ifndef = m.group(1)
+ last_ifndef_lineno = lineno
+ validity_stack.append(last_ifndef not in defines)
+ continue
+
+ # look for "#define BLAH_BLAH" or "#define BLAH_BLAH 42"
+ m = re.match(r"^\s*#define\s+(\w+)(?:\s+(.+?))?\s*$", line)
+ if m:
+ #print(m.groups())
+ name = m.group(1)
+ value = m.group(2)
+ # check all uppercase
+ if name != name.upper():
+ raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
+ # check that adjacent #ifndef and #define lines match up
+ if last_ifndef_lineno + 1 == lineno:
+ if last_ifndef != name:
+ raise Exception("{}:{} #ifndef {} / #define {} mismatch".format(board_header, last_ifndef_lineno, last_ifndef, name))
+ if value:
+ try:
+ # most board-defines are integer values
+ value = int(value, 0)
+ except ValueError:
+ pass
+
+ # resolve nested defines
+ resolved_value = value
+ while resolved_value in defines_dict:
+ resolved_value = defines_dict[resolved_value].resolved_value
+ else:
+ resolved_value = None
+
+ # check for multiply-defined values
+ if name in defines_dict:
+ if defines_dict[name].value != value:
+ raise Exception("{}:{} Conflicting definitions for {} ({} and {})".format(board_header, lineno, name, defines_dict[name].value, value))
+ else:
+ if show_warnings:
+ warnings.warn("{}:{} Multiple definitions for {} ({} and {})".format(board_header, lineno, name, defines_dict[name].value, value))
+ else:
+ defines_dict[name] = DefineType(name, value, resolved_value, lineno)
+
+
+if board_header_basename == "amethyst_fpga.h":
+ defines['PICO_RP2350'] = DefineType('PICO_RP2350', 1, 1, -1)
with open(board_header) as header_fh:
last_ifndef = None
last_ifndef_lineno = -1
+ validity_stack = [True]
board_detection_is_next = False
for lineno, line in enumerate(header_fh.readlines()):
lineno += 1
@@ -65,100 +208,254 @@
line = re.sub(r"(?<=\S)\s*//.*$", "", line)
# look for board-detection comment
- if re.match("// For board detection", line):
+ if re.match("^\s*// For board detection", line):
board_detection_is_next = True
continue
+
# check include-suggestion
- m = re.match(r"^// This header may be included by other board headers as \"(.+?)\"", line)
+ m = re.match("^\s*// This header may be included by other board headers as \"(.+?)\"", line)
if m:
include_suggestion = m.group(1)
if include_suggestion == expected_include_suggestion:
has_include_suggestion = True
else:
- raise Exception(r"{}:{} Suggests including \"{}\" but file is named \"{}\"".format(board_header, lineno, include_suggestion, expected_include_suggestion))
- # look for "#ifndef BLAH_BLAH"
- m = re.match(r"^#ifndef (\w+)\s*$", line)
+ raise Exception("{}:{} Suggests including \"{}\" but file is named \"{}\"".format(board_header, lineno, include_suggestion, expected_include_suggestion))
+ continue
+
+ # look for "// pico_cmake_set BLAH_BLAH=42"
+ m = re.match(r"^\s*//\s*pico_cmake_set\s+(\w+)\s*=\s*(.+?)\s*$", line)
if m:
- last_ifndef = m.group(1)
- last_ifndef_lineno = lineno
- # look for "#define BLAH_BLAH" or "#define BLAH_BLAH 42"
- m = re.match(r"^#define (\w+)(?:\s+(.+?))?\s*$", line)
+ #print(m.groups())
+ name = m.group(1)
+ value = m.group(2)
+ # check all uppercase
+ if name != name.upper():
+ raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
+ # check for multiply-defined values
+ if name in cmake_settings:
+ raise Exception("{}:{} Multiple values for pico_cmake_set {} ({} and {})".format(board_header, lineno, name, cmake_settings[name].value, value))
+ else:
+ if value:
+ try:
+ # most cmake settings are integer values
+ value = int(value, 0)
+ except ValueError:
+ pass
+ cmake_settings[name] = DefineType(name, value, None, lineno)
+ continue
+
+ # look for "// pico_cmake_set_default BLAH_BLAH=42"
+ m = re.match(r"^\s*//\s*pico_cmake_set_default\s+(\w+)\s*=\s*(.+?)\s*$", line)
if m:
#print(m.groups())
name = m.group(1)
value = m.group(2)
# check all uppercase
if name != name.upper():
- raise Exception(r"{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
- # check that adjacent #ifndef and #define lines match up
- if last_ifndef_lineno + 1 == lineno:
- if last_ifndef != name:
- raise Exception("{}:{} #ifndef {} / #define {} mismatch".format(board_header, last_ifndef_lineno, last_ifndef, name))
- if value:
- try:
- # most board-defines are integer values
- value = int(value, 0)
- except ValueError:
- pass
-
- # resolve nested defines
- resolved_value = value
- while resolved_value in defines:
- resolved_value = defines[resolved_value].resolved_value
+ raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
+ # check for multiply-defined values
+ if name in cmake_default_settings:
+ raise Exception("{}:{} Multiple values for pico_cmake_set_default {} ({} and {})".format(board_header, lineno, name, cmake_default_settings[name].value, value))
else:
- resolved_value = None
+ if value:
+ try:
+ # most cmake settings are integer values
+ value = int(value, 0)
+ except ValueError:
+ pass
+ cmake_default_settings[name] = DefineType(name, value, None, lineno)
+ continue
- define = DefineType(name, value, resolved_value, lineno)
+ # look for "#else"
+ m = re.match(r"^\s*#else\s*$", line)
+ if m:
+ validity_stack[-1] = not validity_stack[-1]
+ continue
- # check the include-guard define
- if re.match(r"^_BOARDS_(\w+)_H$", name):
- # check it has an #ifndef
- if last_ifndef_lineno +1 != lineno:
- raise Exception("{}:{} Include-guard #define {} is missing an #ifndef".format(board_header, lineno, name))
- if value:
- raise Exception("{}:{} Include-guard #define {} shouldn't have a value".format(board_header, lineno, name))
- if len(defines):
- raise Exception("{}:{} Include-guard #define {} should be the first define".format(board_header, lineno, name))
- if name == expected_include_guard:
- has_include_guard = True
- else:
- raise Exception("{}:{} Found include-guard #define {} but expected {}".format(board_header, lineno, name, expected_include_guard))
- # check board-detection define
- if board_detection_is_next:
- board_detection_is_next = False
+ # look for #endif
+ m = re.match(r"^\s*#endif\s*$", line)
+ if m:
+ validity_stack.pop()
+ continue
+
+ if validity_stack[-1]:
+ # look for "#include "foo.h"
+ m = re.match(r"""^\s*#include\s+"(.+?)"\s*$""", line)
+ if m:
+ include = m.group(1)
+ #print("Found include \"{}\" in {}".format(include, board_header))
+ assert include.endswith(".h")
+ # assume that the include is also in the boards directory
+ assert "/" not in include or include.startswith("boards/")
+ read_defines_from(os.path.join(os.path.dirname(board_header), os.path.basename(include)), defines)
+ continue
+
+ # look for "#if BLAH_BLAH"
+ m = re.match(r"^\s*#if\s+(!)?\s*(\w+)\s*$", line)
+ if m:
+ valid = bool(defines[m.group(2)].resolved_value)
+ if m.group(1):
+ valid = not valid
+ validity_stack.append(valid)
+ continue
+
+ # look for "#ifdef BLAH_BLAH"
+ m = re.match(r"^\s*#ifdef\s+(\w+)\s*$", line)
+ if m:
+ validity_stack.append(m.group(1) in defines)
+ continue
+
+ # look for "#ifndef BLAH_BLAH"
+ m = re.match(r"^\s*#ifndef\s+(\w+)\s*$", line)
+ if m:
+ last_ifndef = m.group(1)
+ last_ifndef_lineno = lineno
+ validity_stack.append(last_ifndef not in defines)
+ continue
+
+ # look for "#define BLAH_BLAH" or "#define BLAH_BLAH 42"
+ m = re.match(r"^\s*#define\s+(\w+)(?:\s+(.+?))?\s*$", line)
+ if m:
+ #print(m.groups())
+ name = m.group(1)
+ value = m.group(2)
+ # check all uppercase
+ if name != name.upper():
+ raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name))
+ # check that adjacent #ifndef and #define lines match up
+ if last_ifndef_lineno + 1 == lineno:
+ if last_ifndef != name:
+ raise Exception("{}:{} #ifndef {} / #define {} mismatch".format(board_header, last_ifndef_lineno, last_ifndef, name))
if value:
- raise Exception("{}:{} Board-detection #define {} shouldn't have a value".format(board_header, lineno, name))
- # this is a bit messy because pico.h does "#define RASPBERRYPI_PICO" and metrotech_xerxes_rp2040.h does "#define XERXES_RP2040"
- if name.endswith(expected_board_detection) or expected_board_detection.endswith(name):
- has_board_detection = True
- else:
- raise Exception("{}:{} Board-detection #define {} should end with {}".format(board_header, lineno, name, expected_board_detection))
- # check for multiply-defined values
- if name in defines:
- raise Exception("{}:{} Multiple definitions for {} ({} and {})".format(board_header, lineno, name, defines[name].value, value))
- else:
- defines[name] = define
-
- # check for pin-conflicts
- if name.endswith("_PIN"):
- if resolved_value is None:
- raise Exception("{}:{} {} is set to an undefined value".format(board_header, lineno, name))
- elif not isinstance(resolved_value, int):
- raise Exception("{}:{} {} resolves to a non-integer value {}".format(board_header, lineno, name, resolved_value))
+ try:
+ # most board-defines are integer values
+ value = int(value, 0)
+ except ValueError:
+ pass
+
+ # resolve nested defines
+ resolved_value = value
+ while resolved_value in defines:
+ resolved_value = defines[resolved_value].resolved_value
else:
- if resolved_value in pins and resolved_value == value:
- if show_warnings:
- warnings.warn("{}:{} Both {} and {} claim to be pin {}".format(board_header, lineno, pins[resolved_value][0].name, name, resolved_value))
- pins[resolved_value].append(define)
+ resolved_value = None
+
+ # check the include-guard define
+ if re.match(r"^_BOARDS_(\w+)_H$", name):
+ # check it has an #ifndef
+ if last_ifndef_lineno +1 != lineno:
+ raise Exception("{}:{} Include-guard #define {} is missing an #ifndef".format(board_header, lineno, name))
+ if value:
+ raise Exception("{}:{} Include-guard #define {} shouldn't have a value".format(board_header, lineno, name))
+ if len(defines) and not (len(defines) == 1 and defines[list(defines.keys())[0]].lineno < 0):
+ raise Exception("{}:{} Include-guard #define {} should be the first define".format(board_header, lineno, name))
+ if name == expected_include_guard:
+ has_include_guard = True
+ else:
+ raise Exception("{}:{} Found include-guard #define {} but expected {}".format(board_header, lineno, name, expected_include_guard))
+ # check board-detection define
+ if board_detection_is_next:
+ board_detection_is_next = False
+ if value:
+ raise Exception("{}:{} Board-detection #define {} shouldn't have a value".format(board_header, lineno, name))
+ # this is a bit messy because pico.h does "#define RASPBERRYPI_PICO" and metrotech_xerxes_rp2040.h does "#define XERXES_RP2040"
+ if name.endswith(expected_board_detection) or expected_board_detection.endswith(name):
+ has_board_detection = True
else:
- if resolved_value not in allowed_pins:
- raise Exception("{}:{} Pin {} for {} isn't a valid pin-number".format(board_header, lineno, resolved_value, name))
- pins[resolved_value] = [define]
+ raise Exception("{}:{} Board-detection #define {} should end with {}".format(board_header, lineno, name, expected_board_detection))
+ # check for multiply-defined values
+ if name in defines:
+ raise Exception("{}:{} Multiple definitions for {} ({} and {})".format(board_header, lineno, name, defines[name].value, value))
+ else:
+ defines[name] = DefineType(name, value, resolved_value, lineno)
+ continue
+
#import pprint; pprint.pprint(dict(sorted(defines.items(), key=lambda x: x[1].lineno)))
+#import pprint; pprint.pprint(dict(sorted(cmake_settings.items(), key=lambda x: x[1].lineno)))
+#import pprint; pprint.pprint(dict(sorted(cmake_default_settings.items(), key=lambda x: x[1].lineno)))
+chip = None
+if board_header_basename == "none.h":
+ chip = 'RP2040'
+ other_chip = 'RP2350'
+else:
+ for setting in compulsory_cmake_settings:
+ if setting not in cmake_settings:
+ raise Exception("{} is missing a pico_cmake_set {} comment".format(board_header, setting))
+ if cmake_settings['PICO_PLATFORM'].value == "rp2040":
+ chip = 'RP2040'
+ other_chip = 'RP2350'
+ elif cmake_settings['PICO_PLATFORM'].value == "rp2350":
+ other_chip = 'RP2040'
+ if 'PICO_RP2350A' in defines and defines['PICO_RP2350A'].resolved_value == 1:
+ chip = 'RP2350A'
+ else:
+ chip = 'RP2350B'
+ if not board_header.endswith("amethyst_fpga.h"):
+ if 'PICO_RP2350_A2_SUPPORTED' not in cmake_default_settings:
+ raise Exception("{} uses chip {} but is missing a pico_cmake_set_default {} comment".format(board_header, chip, 'PICO_RP2350_A2_SUPPORTED'))
+ if 'PICO_RP2350_A2_SUPPORTED' not in defines:
+ raise Exception("{} uses chip {} but is missing a #define {}".format(board_header, chip, 'PICO_RP2350_A2_SUPPORTED'))
+ if defines['PICO_RP2350_A2_SUPPORTED'].resolved_value != 1:
+ raise Exception("{} sets #define {} {} (should be 1)".format(board_header, chip, 'PICO_RP2350_A2_SUPPORTED', defines['PICO_RP2350_A2_SUPPORTED'].resolved_value))
+ for setting in compulsory_cmake_default_settings:
+ if setting not in cmake_default_settings:
+ raise Exception("{} is missing a pico_cmake_set_default {} comment".format(board_header, setting))
+ for setting in matching_cmake_default_settings:
+ if setting in cmake_default_settings and setting not in defines:
+ raise Exception("{} has pico_cmake_set_default {} but is missing a matching #define".format(board_header, setting))
+ elif setting in defines and setting not in cmake_default_settings:
+ raise Exception("{} has #define {} but is missing a matching pico_cmake_set_default comment".format(board_header, setting))
+ elif setting in defines and setting in cmake_default_settings:
+ if cmake_default_settings[setting].value != defines[setting].resolved_value:
+ raise Exception("{} has mismatched pico_cmake_set_default and #define values for {}".format(board_header, setting))
+ for setting in compulsory_defines:
+ if setting not in defines:
+ raise Exception("{} is missing a #define {}".format(board_header, setting))
-# check for invalid DEFAULT mappings
+if chip is None:
+ raise Exception("Couldn't determine chip for {}".format(board_header))
+interfaces_json = chip_interfaces[chip]
+if not os.path.isfile(interfaces_json):
+ raise Exception("{} doesn't exist".format(interfaces_json))
+
+with open(interfaces_json) as interfaces_fh:
+ interface_pins = json.load(interfaces_fh)
+ allowed_interfaces = interface_pins["interfaces"]
+ allowed_pins = set(interface_pins["pins"])
+ # convert instance-keys to integers (allowed by Python but not by JSON)
+ for interface in allowed_interfaces:
+ instances = allowed_interfaces[interface]["instances"]
+ # can't modify a list that we're iterating over, so iterate over a copy
+ instances_copy = list(instances)
+ for instance in instances_copy:
+ instance_num = int(instance)
+ instances[instance_num] = instances.pop(instance)
+
+pins = dict() # dict of lists
for name, define in defines.items():
+
+ # check for other-chip defines
+ if other_chip in name:
+ raise Exception("{}:{} Header is for {} and so shouldn't have settings for {} ({})".format(board_header, define.lineno, chip, other_chip, name))
+
+ # check for pin-conflicts
+ if name.endswith("_PIN"):
+ if define.resolved_value is None:
+ raise Exception("{}:{} {} is set to an undefined value".format(board_header, define.lineno, name))
+ elif not isinstance(define.resolved_value, int):
+ raise Exception("{}:{} {} resolves to a non-integer value {}".format(board_header, define.lineno, name, define.resolved_value))
+ else:
+ if define.resolved_value in pins and define.resolved_value == define.value:
+ if show_warnings:
+ warnings.warn("{}:{} Both {} and {} claim to be pin {}".format(board_header, define.lineno, pins[define.resolved_value][0].name, name, define.resolved_value))
+ pins[define.resolved_value].append(define)
+ else:
+ if define.resolved_value not in allowed_pins:
+ raise Exception("{}:{} Pin {} for {} isn't a valid pin-number".format(board_header, define.lineno, define.resolved_value, name))
+ pins[define.resolved_value] = [define]
+
+ # check for invalid DEFAULT mappings
m = re.match("^(PICO_DEFAULT_([A-Z0-9]+))_([A-Z0-9]+)_PIN$", name)
if m:
instance_name = m.group(1)
@@ -180,17 +477,7 @@
if define.resolved_value not in interface_instance[function]:
raise Exception("{}:{} {} is set to {} which isn't a valid pin for {} on {} {}".format(board_header, define.lineno, name, define.resolved_value, function, interface, instance_num))
-def list_to_string_with(lst, joiner):
- elems = len(lst)
- if elems == 0:
- return ""
- elif elems == 1:
- return str(lst[0])
- else:
- return "{} {} {}".format(", ".join(str(l) for l in lst[:-1]), joiner, lst[-1])
-
-# check that each used DEFAULT interface includes (at least) the expected pin-functions
-for name, define in defines.items():
+ # check that each used DEFAULT interface includes (at least) the expected pin-functions
m = re.match("^PICO_DEFAULT_([A-Z0-9]+)$", name)
if m:
interface = m.group(1)
@@ -216,3 +503,5 @@ def list_to_string_with(lst, joiner):
#if not has_include_suggestion:
# raise Exception("{} has no include-suggestion (expected {})".format(board_header, expected_include_suggestion))
+# Check that #if / #ifdef / #ifndef / #else / #endif are correctly balanced
+assert len(validity_stack) == 1 and validity_stack[0]
diff --git a/tools/compare_build_systems.py b/tools/compare_build_systems.py
index c5762817b..badeadee1 100755
--- a/tools/compare_build_systems.py
+++ b/tools/compare_build_systems.py
@@ -14,12 +14,17 @@
from dataclasses import dataclass
import glob
+import logging
import os
+from pathlib import Path
import re
+import subprocess
import sys
from typing import Dict
-from bazel_common import SDK_ROOT
+from bazel_common import SDK_ROOT, setup_logging
+
+_LOG = logging.getLogger(__file__)
CMAKE_FILE_TYPES = (
"**/CMakeLists.txt",
@@ -34,6 +39,12 @@
ATTR_REGEX = re.compile(r",?\s*(?P[^=]+)=(?P[^,]+)")
+BAZEL_MODULE_REGEX = re.compile(r'\s*commit\s*=\s*\"(?P[0-9a-fA-F]+)\"\s*,\s*#\s*keep-in-sync-with-submodule:\s*(?P\S*)')
+
+BAZEL_VERSION_REGEX = re.compile(r'module\(\s*name\s*=\s*"pico-sdk",\s*version\s*=\s*"(?P[^"]+)",?\s*\)')
+
+CMAKE_VERSION_REGEX = re.compile(r'^[^#]*set\(PICO_SDK_VERSION_(?P\S+)\s+(?P\S+)\)')
+
# Sometimes the build systems are supposed to be implemented differently. This
# allowlist permits the descriptions to differ between CMake and Bazel.
BUILD_SYSTEM_DESCRIPTION_DIFFERENCE_ALLOWLIST = (
@@ -57,7 +68,7 @@
"PICO_TOOLCHAIN_PATH",
# Bazel uses native --platforms mechanics.
"PICO_PLATFORM",
- # TODO: No built-in, pre-configured clang offering for Bazel yet.
+ # Named PICO_TOOLCHAIN in Bazel.
"PICO_COMPILER",
# Entirely irrelevant to Bazel, use Bazel platforms:
# https://bazel.build/extending/platforms
@@ -84,14 +95,17 @@
"PICO_DEFAULT_PIOASM_OUTPUT_FORMAT",
# Bazel always has picotool.
"PICO_NO_PICOTOOL",
- # TODO: Eventualy support.
- "PICO_NO_COPRO_DIS",
- "PICO_DEFAULT_RP2350_PLATFORM",
- "PICO_GCC_TRIPLE",
- "PICO_NO_FLASH",
- "PICO_COPY_TO_RAM",
- "PICO_RP2350_ARM_S_CONFIG_HEADER_FILES",
- "PICO_RP2350_RISCV_CONFIG_HEADER_FILES",
+ # These aren't supported as build flags in Bazel. Prefer to
+ # set these in board header files like other SDK defines.
+ "CYW43_DEFAULT_PIN_WL_REG_ON",
+ "CYW43_DEFAULT_PIN_WL_DATA_OUT",
+ "CYW43_DEFAULT_PIN_WL_DATA_IN",
+ "CYW43_DEFAULT_PIN_WL_HOST_WAKE",
+ "CYW43_DEFAULT_PIN_WL_CLOCK",
+ "CYW43_DEFAULT_PIN_WL_CS",
+ "CYW43_PIO_CLOCK_DIV_INT",
+ "CYW43_PIO_CLOCK_DIV_FRAC",
+ "CYW43_PIO_CLOCK_DIV_DYNAMIC",
)
BAZEL_ONLY_ALLOWLIST = (
@@ -133,9 +147,16 @@
"PICO_DEFAULT_PRINTF_IMPL",
"PICO_DEFAULT_RAND_IMPL",
"PICO_BINARY_INFO_ENABLED",
+ "PICO_ASYNC_CONTEXT_IMPL",
# Allows selection of clang/gcc when using the dynamically fetched
# toolchains.
"PICO_TOOLCHAIN",
+ # In CMake, linking these libraries also sets defines for adjacent
+ # libraries. That's an antipattern in Bazel, so there's flags to control
+ # which modules to enable instead.
+ "PICO_BT_ENABLE_BLE",
+ "PICO_BT_ENABLE_CLASSIC",
+ "PICO_BT_ENABLE_MESH",
)
@@ -178,27 +199,27 @@ def FindKnownOptions(option_pattern_matcher, file_paths):
return options
-def OptionsAreEqual(bazel_option, cmake_option):
+def OptionsAreEqual(bazel_option, cmake_option, warnings_as_errors):
if bazel_option is None:
if cmake_option.name in CMAKE_ONLY_ALLOWLIST:
return True
- print(f" {cmake_option.name} does not exist in Bazel")
- return False
+ _LOG.warning(f" {cmake_option.name} does not exist in Bazel")
+ return not warnings_as_errors
elif cmake_option is None:
if bazel_option.name in BAZEL_ONLY_ALLOWLIST:
return True
- print(f" {bazel_option.name} does not exist in CMake")
- return False
+ _LOG.warning(f" {bazel_option.name} does not exist in CMake")
+ return not warnings_as_errors
elif not bazel_option.matches(cmake_option):
- print(" Bazel and CMAKE definitions do not match:")
- print(f" [CMAKE] {bazel_option}")
- print(f" [BAZEL] {cmake_option}")
+ _LOG.error(" Bazel and CMAKE definitions do not match:")
+ _LOG.error(f" [CMAKE] {bazel_option}")
+ _LOG.error(f" [BAZEL] {cmake_option}")
return False
return True
-def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files):
+def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files, warnings_as_errors=True):
bazel_options = FindKnownOptions(bazel_pattern, bazel_files)
cmake_options = FindKnownOptions(cmake_pattern, cmake_files)
@@ -207,10 +228,72 @@ def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files):
both.update(bazel_options)
both.update(cmake_options)
for k in both.keys():
- if not OptionsAreEqual(bazel_options.get(k, None), cmake_options.get(k, None)):
+ if not OptionsAreEqual(
+ bazel_options.get(k, None),
+ cmake_options.get(k, None),
+ warnings_as_errors,
+ ):
are_equal = False
return are_equal
+def CompareExternalDependencyVersions():
+ pattern = re.compile(BAZEL_MODULE_REGEX)
+ all_okay = True
+ with open(Path(SDK_ROOT) / "MODULE.bazel", "r") as bazel_module_file:
+ for line in bazel_module_file:
+ maybe_match = pattern.match(line)
+ if not maybe_match:
+ continue
+
+ current_submodule_pin = subprocess.run(
+ ("git", "-C", SDK_ROOT, "rev-parse", f'HEAD:{maybe_match.group("dependency")}'),
+ text=True,
+ check=True,
+ capture_output=True,
+ ).stdout.strip()
+ if current_submodule_pin != maybe_match.group("commit"):
+ _LOG.error(" External pins for %s do not match:", maybe_match.group("dependency"))
+ _LOG.error(" [CMAKE] %s", current_submodule_pin)
+ _LOG.error(" [BAZEL] %s", maybe_match.group("commit"))
+ all_okay = False
+ else:
+ _LOG.info(" External pins for %s match!", maybe_match.group("dependency"))
+
+ return all_okay
+
+def CompareSdkVersion():
+ # Find version string specified in Bazel.
+ bazel_module_file_path = Path(SDK_ROOT) / "MODULE.bazel"
+ bazel_module_file_contents = bazel_module_file_path.read_text()
+ bazel_sdk_version = BAZEL_VERSION_REGEX.search(bazel_module_file_contents)
+ if not bazel_sdk_version:
+ _LOG.error(" Failed to find Bazel Pico SDK version string")
+ return False
+ bazel_version_string = bazel_sdk_version.group("sdk_version")
+
+ # Find version string specified in CMake.
+ cmake_version_parts = {}
+ with open(Path(SDK_ROOT) / "pico_sdk_version.cmake", "r") as cmake_version_file:
+ for line in cmake_version_file:
+ match = CMAKE_VERSION_REGEX.match(line)
+ if match:
+ cmake_version_parts[match.group("part")] = match.group("value")
+ if len(cmake_version_parts) < 3:
+ _LOG.error(" Failed to find CMake Pico SDK version string")
+ return False
+ cmake_version_string = ".".join((
+ cmake_version_parts["MAJOR"],
+ cmake_version_parts["MINOR"],
+ cmake_version_parts["REVISION"],
+ ))
+ if "PRE_RELEASE_ID" in cmake_version_parts:
+ cmake_version_string += "-" + cmake_version_parts["PRE_RELEASE_ID"]
+
+ if cmake_version_string != bazel_version_string:
+ _LOG.error(" Declared CMake SDK version is %s and Bazel is %s", cmake_version_string, bazel_version_string)
+ return False
+
+ return True
def compare_build_systems():
cmake_files = [
@@ -224,22 +307,38 @@ def compare_build_systems():
for f in glob.glob(os.path.join(SDK_ROOT, p), recursive=True)
]
- print("[1/2] Checking build system configuration flags...")
- build_options_ok = CompareOptions(
- "PICO_BAZEL_CONFIG", bazel_files, "PICO_CMAKE_CONFIG", cmake_files
- )
+ results = []
+ _LOG.info("[1/3] Checking build system configuration flags...")
+ results.append(CompareOptions(
+ "PICO_BAZEL_CONFIG",
+ bazel_files,
+ "PICO_CMAKE_CONFIG",
+ cmake_files,
+ # For now, allow CMake and Bazel to go out of sync when it comes to
+ # build configurability since it's a big ask to make contributors
+ # implement the same functionality in both builds.
+ warnings_as_errors=False,
+ ))
- print("[2/2] Checking build system defines...")
- build_defines_ok = CompareOptions(
+ _LOG.info("[2/4] Checking build system defines...")
+ results.append(CompareOptions(
"PICO_BUILD_DEFINE", bazel_files, "PICO_BUILD_DEFINE", cmake_files
- )
+ ))
+
+ _LOG.info("[3/4] Checking submodule pins...")
+ results.append(CompareExternalDependencyVersions())
+
+ _LOG.info("[4/4] Checking version strings...")
+ results.append(CompareSdkVersion())
- if build_options_ok and build_defines_ok:
- print("OK")
+ if False not in results:
+ _LOG.info("Passed with no blocking failures")
return 0
+ _LOG.error("One or more blocking failures detected")
return 1
if __name__ == "__main__":
+ setup_logging()
sys.exit(compare_build_systems())
diff --git a/tools/copro_dis.py b/tools/copro_dis.py
index 285bc7be2..2e03f8985 100644
--- a/tools/copro_dis.py
+++ b/tools/copro_dis.py
@@ -1,4 +1,7 @@
#!/usr/bin/env python3
+
+# NOTE THIS SCRIPT IS DEPRECATED. Use 'picotool coprodis' instead
+
import argparse, re
parser = argparse.ArgumentParser(description="Disassemble RCP instructions in DIS file")
@@ -61,6 +64,7 @@ def gpioxsc(val):
(r'mcr2\s*p?7, #?0, (.*), cr?(.*), cr?(.*), [\{#]1}?', lambda m: 'rcp_canary_check {0}, 0x{1:02x} ({1}), nodelay'.format(m.group(1), int(m.group(2)) * 16 + int(m.group(3)))),
(r'mrc\s*p?7, #?1, (.*), cr?(.*), cr?(.*), [\{#]0}?', r'rcp_canary_status \1, delay'),
+ (r'mrc2\s*p?7, #?1, (.*), cr?(.*), cr?(.*), [\{#]0}?', r'rcp_canary_status \1, nodelay'),
(r'mcr\s*p?7, #?1, (.*), cr?(.*), cr?(.*), [\{#]0}?', r'rcp_bvalid \1, delay'),
(r'mcr2\s*p?7, #?1, (.*), cr?(.*), cr?(.*), [\{#]0}?', r'rcp_bvalid \1, nodelay'),
diff --git a/tools/extract_build_defines.py b/tools/extract_build_defines.py
index 221a25568..bbcad15af 100755
--- a/tools/extract_build_defines.py
+++ b/tools/extract_build_defines.py
@@ -7,7 +7,7 @@
#
# Script to scan the Raspberry Pi Pico SDK tree searching for CMake build defines
# Outputs a tab separated file of the configuration item:
-# name location description type default group
+# name location platform chip description type default group
#
# Usage:
#
@@ -22,24 +22,41 @@
import csv
import logging
+from collections import defaultdict
+
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
scandir = sys.argv[1]
outfile = sys.argv[2] if len(sys.argv) > 2 else 'pico_build_defines.tsv'
-BUILD_DEFINE_RE = re.compile(r'#\s+PICO_BUILD_DEFINE:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$')
+BASE_CONFIG_NAME = 'PICO_CONFIG'
+BASE_CONFIG_RE = re.compile(r'\b{}\b'.format(BASE_CONFIG_NAME))
+BASE_CMAKE_CONFIG_NAME = 'PICO_CMAKE_CONFIG'
+BASE_CMAKE_CONFIG_RE = re.compile(r'\b{}\b'.format(BASE_CMAKE_CONFIG_NAME))
+BASE_BUILD_DEFINE_NAME = 'PICO_BUILD_DEFINE'
+BASE_BUILD_DEFINE_RE = re.compile(r'\b{}\b'.format(BASE_BUILD_DEFINE_NAME))
+
+BUILD_DEFINE_RE = re.compile(r'#\s+{}:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$'.format(BASE_BUILD_DEFINE_NAME))
+
+ALLOWED_CONFIG_PROPERTIES = set(['type', 'default', 'min', 'max', 'group'])
-all_configs = {}
+CHIP_NAMES = ["rp2040", "rp2350"]
+
+chips_all_configs = defaultdict(dict)
all_attrs = set()
-all_descriptions = {}
+chips_all_descriptions = defaultdict(dict)
-def ValidateAttrs(config_attrs, file_path, linenum):
+def ValidateAttrs(config_name, config_attrs, file_path, linenum):
_type = config_attrs.get('type')
# Validate attrs
+ for key in config_attrs.keys():
+ if key not in ALLOWED_CONFIG_PROPERTIES:
+ raise Exception('{} at {}:{} has unexpected property "{}"'.format(config_name, file_path, linenum, key))
+
if _type == 'int':
_min = _max = _default = None
if config_attrs.get('min', None) is not None:
@@ -82,7 +99,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
_default = config_attrs.get('default', None)
if _default is not None:
if '/' not in _default:
- if (_default.lower() != '0') and (config_attrs['default'].lower() != '1') and ( _default not in all_configs):
+ if (_default not in ('0', '1')) and (_default not in all_config_names):
logger.info('{} at {}:{} has non-integer default value "{}"'.format(config_name, file_path, linenum, config_attrs['default']))
elif _type == 'string':
@@ -94,7 +111,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
assert 'max' not in config_attrs
_default = config_attrs.get('default', None)
else:
- raise Exception("Found unknown PICO_BUILD_DEFINE type {} at {}:{}".format(_type, file_path, linenum))
+ raise Exception("Found unknown {} type {} at {}:{}".format(BASE_BUILD_DEFINE_NAME, _type, file_path, linenum))
@@ -106,63 +123,137 @@ def ValidateAttrs(config_attrs, file_path, linenum):
file_ext = os.path.splitext(filename)[1]
if filename == 'CMakeLists.txt' or file_ext == '.cmake':
file_path = os.path.join(dirpath, filename)
+ applicable = "all"
+ for chip in (*CHIP_NAMES, "host"):
+ if "/{}/".format(chip) in dirpath:
+ applicable = chip
+ break
with open(file_path, encoding="ISO-8859-1") as fh:
linenum = 0
for line in fh.readlines():
linenum += 1
line = line.strip()
- m = BUILD_DEFINE_RE.match(line)
- if m:
- config_name = m.group(1)
- config_description = m.group(2)
- _attrs = m.group(3)
- # allow commas to appear inside brackets by converting them to and from NULL chars
- _attrs = re.sub(r'(\(.+\))', lambda m: m.group(1).replace(',', '\0'), _attrs)
-
- if '=' in config_description:
- raise Exception("For {} at {}:{} the description was set to '{}' - has the description field been omitted?".format(config_name, file_path, linenum, config_description))
- if config_description in all_descriptions:
- raise Exception("Found description {} at {}:{} but it was already used at {}:{}".format(config_description, file_path, linenum, os.path.join(scandir, all_descriptions[config_description]['filename']), all_descriptions[config_description]['line_number']))
- else:
- all_descriptions[config_description] = {'config_name': config_name, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum}
-
- config_attrs = {}
- prev = None
- # Handle case where attr value contains a comma
- for item in _attrs.split(','):
- if "=" not in item:
- assert(prev)
- item = prev + "," + item
- try:
- k, v = (i.strip() for i in item.split('='))
- except ValueError:
- raise Exception('{} at {}:{} has malformed value {}'.format(config_name, file_path, linenum, item))
- config_attrs[k] = v.replace('\0', ',')
- all_attrs.add(k)
- prev = item
- #print(file_path, config_name, config_attrs)
-
- if 'group' not in config_attrs:
- raise Exception('{} at {}:{} has no group attribute'.format(config_name, file_path, linenum))
-
- #print(file_path, config_name, config_attrs)
- if config_name in all_configs:
- raise Exception("Found {} at {}:{} but it was already declared at {}:{}".format(config_name, file_path, linenum, os.path.join(scandir, all_configs[config_name]['filename']), all_configs[config_name]['line_number']))
+ if BASE_CONFIG_RE.search(line):
+ raise Exception("Found {} at {}:{} ({}) which isn't expected in {} files".format(BASE_CONFIG_NAME, file_path, linenum, line, filename if filename == 'CMakeLists.txt' else file_ext))
+ elif BASE_BUILD_DEFINE_RE.search(line):
+ m = BUILD_DEFINE_RE.match(line)
+ if not m:
+ if line.startswith("## "):
+ logger.info("Possible misformatted {} at {}:{} ({})".format(BASE_BUILD_DEFINE_NAME, file_path, linenum, line))
+ else:
+ raise Exception("Found misformatted {} at {}:{} ({})".format(BASE_BUILD_DEFINE_NAME, file_path, linenum, line))
else:
- all_configs[config_name] = {'attrs': config_attrs, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum, 'description': config_description}
+ config_name = m.group(1)
+ config_description = m.group(2)
+ _attrs = m.group(3)
+ # allow commas to appear inside brackets by converting them to and from NULL chars
+ _attrs = re.sub(r'(\(.+\))', lambda m: m.group(1).replace(',', '\0'), _attrs)
+
+ if '=' in config_description:
+ raise Exception("For {} at {}:{} the description was set to '{}' - has the description field been omitted?".format(config_name, file_path, linenum, config_description))
+ all_descriptions = chips_all_descriptions[applicable]
+ if config_description in all_descriptions:
+ raise Exception("Found description {} at {}:{} but it was already used at {}:{}".format(config_description, file_path, linenum, os.path.join(scandir, all_descriptions[config_description]['filename']), all_descriptions[config_description]['line_number']))
+ else:
+ all_descriptions[config_description] = {'config_name': config_name, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum}
+
+ config_attrs = {}
+ prev = None
+ # Handle case where attr value contains a comma
+ for item in _attrs.split(','):
+ if "=" not in item:
+ assert(prev)
+ item = prev + "," + item
+ try:
+ k, v = (i.strip() for i in item.split('='))
+ except ValueError:
+ raise Exception('{} at {}:{} has malformed value {}'.format(config_name, file_path, linenum, item))
+ config_attrs[k] = v.replace('\0', ',')
+ all_attrs.add(k)
+ prev = item
+ #print(file_path, config_name, config_attrs)
+
+ if 'group' not in config_attrs:
+ raise Exception('{} at {}:{} has no group attribute'.format(config_name, file_path, linenum))
+
+ #print(file_path, config_name, config_attrs)
+ all_configs = chips_all_configs[applicable]
+ if config_name in all_configs:
+ raise Exception("Found {} at {}:{} but it was already declared at {}:{}".format(config_name, file_path, linenum, os.path.join(scandir, all_configs[config_name]['filename']), all_configs[config_name]['line_number']))
+ else:
+ all_configs[config_name] = {'attrs': config_attrs, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum, 'description': config_description}
+
+
+all_config_names = set()
+for all_configs in chips_all_configs.values():
+ all_config_names.update(all_configs.keys())
+
+for applicable, all_configs in chips_all_configs.items():
+ for config_name, config_obj in all_configs.items():
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
+
+ ValidateAttrs(config_name, config_obj['attrs'], file_path, linenum)
+
+# All settings in "host" should also be in "all"
+for config_name, config_obj in chips_all_configs["host"].items():
+ if config_name not in chips_all_configs["all"]:
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
+ raise Exception("Found 'host' config {} at {}:{}, but no matching non-host config found".format(config_name, file_path, linenum))
+
+# Any chip-specific settings should not be in "all"
+for chip in CHIP_NAMES:
+ for config_name, chip_config_obj in chips_all_configs[chip].items():
+ if config_name in chips_all_configs["all"]:
+ all_config_obj = chips_all_configs["all"][config_name]
+ chip_file_path = os.path.join(scandir, chip_config_obj['filename'])
+ chip_linenum = chip_config_obj['line_number']
+ all_file_path = os.path.join(scandir, all_config_obj['filename'])
+ all_linenum = all_config_obj['line_number']
+ raise Exception("'{}' config {} at {}:{} also found at {}:{}".format(chip, config_name, chip_file_path, chip_linenum, all_file_path, all_linenum))
+def build_mismatch_exception_message(name, thing, config_obj1, value1, config_obj2, value2):
+ obj1_filepath = os.path.join(scandir, config_obj1['filename'])
+ obj2_filepath = os.path.join(scandir, config_obj2['filename'])
+ return "'{}' {} mismatch at {}:{} ({}) and {}:{} ({})".format(name, thing, obj1_filepath, config_obj1['line_number'], value1, obj2_filepath, config_obj2['line_number'], value2)
-for config_name, config_obj in all_configs.items():
- file_path = os.path.join(scandir, config_obj['filename'])
- linenum = config_obj['line_number']
+# Check that any identically-named setttings have appropriate matching attributes
+for applicable in chips_all_configs:
+ for other in chips_all_configs:
+ if other == applicable:
+ continue
+ for config_name, applicable_config_obj in chips_all_configs[applicable].items():
+ if config_name in chips_all_configs[other]:
+ other_config_obj = chips_all_configs[other][config_name]
+ # Check that fields match
+ for field in ['description']:
+ applicable_value = applicable_config_obj[field]
+ other_value = other_config_obj[field]
+ if applicable_value != other_value:
+ raise Exception(build_mismatch_exception_message(config_name, field, applicable_config_obj, applicable_value, other_config_obj, other_value))
+ # Check that attributes match
+ for attr in applicable_config_obj['attrs']:
+ if attr != 'default': # totally fine for defaults to vary per-platform
+ applicable_value = applicable_config_obj['attrs'][attr]
+ other_value = other_config_obj['attrs'][attr]
+ if applicable_value != other_value:
+ raise Exception(build_mismatch_exception_message(config_name, "attribute '{}'".format(attr), applicable_config_obj, applicable_value, other_config_obj, other_value))
- ValidateAttrs(config_obj['attrs'], file_path, linenum)
+# Sort the output alphabetically by name and then by chip
+output_rows = set()
+for chip in (*CHIP_NAMES, "host", "all"):
+ if chip in chips_all_configs:
+ all_configs = chips_all_configs[chip]
+ for config_name in all_configs:
+ output_rows.add((config_name, chip))
with open(outfile, 'w', newline='') as csvfile:
- fieldnames = ('name', 'location', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
+ fieldnames = ('name', 'location', 'platform', 'chip', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', dialect='excel-tab')
writer.writeheader()
- for config_name, config_obj in sorted(all_configs.items()):
- writer.writerow({'name': config_name, 'location': '/{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'description': config_obj['description'], **config_obj['attrs']})
+ for config_name, chip in sorted(output_rows):
+ config_obj = chips_all_configs[chip][config_name]
+ writer.writerow({'name': config_name, 'location': '/{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'platform': "host" if chip == "host" else "rp2", 'chip': chip if chip in CHIP_NAMES else "all", 'description': config_obj['description'], **config_obj['attrs']})
diff --git a/tools/extract_cmake_configs.py b/tools/extract_cmake_configs.py
index 507429f46..8fdb4504e 100755
--- a/tools/extract_cmake_configs.py
+++ b/tools/extract_cmake_configs.py
@@ -7,7 +7,7 @@
#
# Script to scan the Raspberry Pi Pico SDK tree searching for CMake configuration items
# Outputs a tab separated file of the configuration item:
-# name location description type advanced default group
+# name location platform chip description type advanced default docref group
#
# Usage:
#
@@ -22,24 +22,41 @@
import csv
import logging
+from collections import defaultdict
+
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
scandir = sys.argv[1]
outfile = sys.argv[2] if len(sys.argv) > 2 else 'pico_cmake_configs.tsv'
-CMAKE_CONFIG_RE = re.compile(r'#\s+PICO_CMAKE_CONFIG:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$')
+BASE_CONFIG_NAME = 'PICO_CONFIG'
+BASE_CONFIG_RE = re.compile(r'\b{}\b'.format(BASE_CONFIG_NAME))
+BASE_CMAKE_CONFIG_NAME = 'PICO_CMAKE_CONFIG'
+BASE_CMAKE_CONFIG_RE = re.compile(r'\b{}\b'.format(BASE_CMAKE_CONFIG_NAME))
+BASE_BUILD_DEFINE_NAME = 'PICO_BUILD_DEFINE'
+BASE_BUILD_DEFINE_RE = re.compile(r'\b{}\b'.format(BASE_BUILD_DEFINE_NAME))
+
+CMAKE_CONFIG_RE = re.compile(r'#\s+{}:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$'.format(BASE_CMAKE_CONFIG_NAME))
+
+ALLOWED_CONFIG_PROPERTIES = set(['type', 'default', 'min', 'max', 'group', 'advanced', 'docref'])
-all_configs = {}
+CHIP_NAMES = ["rp2040", "rp2350"]
+
+chips_all_configs = defaultdict(dict)
all_attrs = set()
-all_descriptions = {}
+chips_all_descriptions = defaultdict(dict)
-def ValidateAttrs(config_attrs, file_path, linenum):
+def ValidateAttrs(config_name, config_attrs, file_path, linenum):
_type = config_attrs.get('type')
# Validate attrs
+ for key in config_attrs.keys():
+ if key not in ALLOWED_CONFIG_PROPERTIES:
+ raise Exception('{} at {}:{} has unexpected property "{}"'.format(config_name, file_path, linenum, key))
+
if _type == 'int':
_min = _max = _default = None
if config_attrs.get('min', None) is not None:
@@ -82,7 +99,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
_default = config_attrs.get('default', None)
if _default is not None:
if '/' not in _default:
- if (_default.lower() != '0') and (config_attrs['default'].lower() != '1') and ( _default not in all_configs):
+ if (_default not in ('0', '1')) and (_default not in all_config_names):
logger.info('{} at {}:{} has non-integer default value "{}"'.format(config_name, file_path, linenum, config_attrs['default']))
elif _type == 'string':
@@ -94,7 +111,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
assert 'max' not in config_attrs
_default = config_attrs.get('default', None)
else:
- raise Exception("Found unknown PICO_CMAKE_CONFIG type {} at {}:{}".format(_type, file_path, linenum))
+ raise Exception("Found unknown {} type {} at {}:{}".format(BASE_CMAKE_CONFIG_NAME, _type, file_path, linenum))
@@ -106,72 +123,137 @@ def ValidateAttrs(config_attrs, file_path, linenum):
file_ext = os.path.splitext(filename)[1]
if filename == 'CMakeLists.txt' or file_ext == '.cmake':
file_path = os.path.join(dirpath, filename)
+ applicable = "all"
+ for chip in (*CHIP_NAMES, "host"):
+ if "/{}/".format(chip) in dirpath:
+ applicable = chip
+ break
with open(file_path, encoding="ISO-8859-1") as fh:
linenum = 0
for line in fh.readlines():
linenum += 1
line = line.strip()
- m = CMAKE_CONFIG_RE.match(line)
- if m:
- config_name = m.group(1)
- config_description = m.group(2)
- _attrs = m.group(3)
- # allow commas to appear inside brackets by converting them to and from NULL chars
- _attrs = re.sub(r'(\(.+\))', lambda m: m.group(1).replace(',', '\0'), _attrs)
-
- if '=' in config_description:
- raise Exception("For {} at {}:{} the description was set to '{}' - has the description field been omitted?".format(config_name, file_path, linenum, config_description))
- if config_description in all_descriptions:
- # relax check for the same header/variable in a different tree
- if config_name != all_descriptions[config_description]['config_name'] or filename != all_descriptions[config_description]['filename_only']:
- raise Exception("Found description {} at {}:{} but it was already used at {}:{}".format(config_description, file_path, linenum, os.path.join(scandir, all_descriptions[config_description]['filename']), all_descriptions[config_description]['line_number']))
+ if BASE_CONFIG_RE.search(line):
+ raise Exception("Found {} at {}:{} ({}) which isn't expected in {} files".format(BASE_CONFIG_NAME, file_path, linenum, line, filename if filename == 'CMakeLists.txt' else file_ext))
+ elif BASE_CMAKE_CONFIG_RE.search(line):
+ m = CMAKE_CONFIG_RE.match(line)
+ if not m:
+ if line.startswith("## "):
+ logger.info("Possible misformatted {} at {}:{} ({})".format(BASE_CMAKE_CONFIG_NAME, file_path, linenum, line))
+ else:
+ raise Exception("Found misformatted {} at {}:{} ({})".format(BASE_CMAKE_CONFIG_NAME, file_path, linenum, line))
else:
- all_descriptions[config_description] = {'config_name': config_name, 'filename': os.path.relpath(file_path, scandir), 'filename_only':filename, 'line_number': linenum}
-
- config_attrs = {}
- prev = None
- # Handle case where attr value contains a comma
- for item in _attrs.split(','):
- if "=" not in item:
- assert(prev)
- item = prev + "," + item
- try:
- k, v = (i.strip() for i in item.split('='))
- except ValueError:
- raise Exception('{} at {}:{} has malformed value {}'.format(config_name, file_path, linenum, item))
- config_attrs[k] = v.replace('\0', ',')
- all_attrs.add(k)
- prev = item
- #print(file_path, config_name, config_attrs)
-
- if 'group' not in config_attrs:
- raise Exception('{} at {}:{} has no group attribute'.format(config_name, file_path, linenum))
-
- #print(file_path, config_name, config_attrs)
- if config_name in all_configs:
- # relax check for the same header/variable in a different tree
- if filename != all_configs[config_name]['filename_only']:
+ config_name = m.group(1)
+ config_description = m.group(2)
+ _attrs = m.group(3)
+ # allow commas to appear inside brackets by converting them to and from NULL chars
+ _attrs = re.sub(r'(\(.+\))', lambda m: m.group(1).replace(',', '\0'), _attrs)
+
+ if '=' in config_description:
+ raise Exception("For {} at {}:{} the description was set to '{}' - has the description field been omitted?".format(config_name, file_path, linenum, config_description))
+ all_descriptions = chips_all_descriptions[applicable]
+ if config_description in all_descriptions:
+ raise Exception("Found description {} at {}:{} but it was already used at {}:{}".format(config_description, file_path, linenum, os.path.join(scandir, all_descriptions[config_description]['filename']), all_descriptions[config_description]['line_number']))
+ else:
+ all_descriptions[config_description] = {'config_name': config_name, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum}
+
+ config_attrs = {}
+ prev = None
+ # Handle case where attr value contains a comma
+ for item in _attrs.split(','):
+ if "=" not in item:
+ assert(prev)
+ item = prev + "," + item
+ try:
+ k, v = (i.strip() for i in item.split('='))
+ except ValueError:
+ raise Exception('{} at {}:{} has malformed value {}'.format(config_name, file_path, linenum, item))
+ config_attrs[k] = v.replace('\0', ',')
+ all_attrs.add(k)
+ prev = item
+ #print(file_path, config_name, config_attrs)
+
+ if 'group' not in config_attrs:
+ raise Exception('{} at {}:{} has no group attribute'.format(config_name, file_path, linenum))
+
+ #print(file_path, config_name, config_attrs)
+ all_configs = chips_all_configs[applicable]
+ if config_name in all_configs:
raise Exception("Found {} at {}:{} but it was already declared at {}:{}".format(config_name, file_path, linenum, os.path.join(scandir, all_configs[config_name]['filename']), all_configs[config_name]['line_number']))
- else:
- all_configs[config_name] = {'attrs': config_attrs, 'filename': os.path.relpath(file_path, scandir), 'filename_only' : filename, 'line_number': linenum, 'description': config_description}
+ else:
+ all_configs[config_name] = {'attrs': config_attrs, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum, 'description': config_description}
+
+
+all_config_names = set()
+for all_configs in chips_all_configs.values():
+ all_config_names.update(all_configs.keys())
+
+for applicable, all_configs in chips_all_configs.items():
+ for config_name, config_obj in all_configs.items():
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
+
+ ValidateAttrs(config_name, config_obj['attrs'], file_path, linenum)
+
+# All settings in "host" should also be in "all"
+for config_name, config_obj in chips_all_configs["host"].items():
+ if config_name not in chips_all_configs["all"]:
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
+ raise Exception("Found 'host' config {} at {}:{}, but no matching non-host config found".format(config_name, file_path, linenum))
+
+# Any chip-specific settings should not be in "all"
+for chip in CHIP_NAMES:
+ for config_name, chip_config_obj in chips_all_configs[chip].items():
+ if config_name in chips_all_configs["all"]:
+ all_config_obj = chips_all_configs["all"][config_name]
+ chip_file_path = os.path.join(scandir, chip_config_obj['filename'])
+ chip_linenum = chip_config_obj['line_number']
+ all_file_path = os.path.join(scandir, all_config_obj['filename'])
+ all_linenum = all_config_obj['line_number']
+ raise Exception("'{}' config {} at {}:{} also found at {}:{}".format(chip, config_name, chip_file_path, chip_linenum, all_file_path, all_linenum))
+def build_mismatch_exception_message(name, thing, config_obj1, value1, config_obj2, value2):
+ obj1_filepath = os.path.join(scandir, config_obj1['filename'])
+ obj2_filepath = os.path.join(scandir, config_obj2['filename'])
+ return "'{}' {} mismatch at {}:{} ({}) and {}:{} ({})".format(name, thing, obj1_filepath, config_obj1['line_number'], value1, obj2_filepath, config_obj2['line_number'], value2)
-for config_name, config_obj in all_configs.items():
- file_path = os.path.join(scandir, config_obj['filename'])
- linenum = config_obj['line_number']
+# Check that any identically-named setttings have appropriate matching attributes
+for applicable in chips_all_configs:
+ for other in chips_all_configs:
+ if other == applicable:
+ continue
+ for config_name, applicable_config_obj in chips_all_configs[applicable].items():
+ if config_name in chips_all_configs[other]:
+ other_config_obj = chips_all_configs[other][config_name]
+ # Check that fields match
+ for field in ['description']:
+ applicable_value = applicable_config_obj[field]
+ other_value = other_config_obj[field]
+ if applicable_value != other_value:
+ raise Exception(build_mismatch_exception_message(config_name, field, applicable_config_obj, applicable_value, other_config_obj, other_value))
+ # Check that attributes match
+ for attr in applicable_config_obj['attrs']:
+ if attr != 'default': # totally fine for defaults to vary per-platform
+ applicable_value = applicable_config_obj['attrs'][attr]
+ other_value = other_config_obj['attrs'][attr]
+ if applicable_value != other_value:
+ raise Exception(build_mismatch_exception_message(config_name, "attribute '{}'".format(attr), applicable_config_obj, applicable_value, other_config_obj, other_value))
- ValidateAttrs(config_obj['attrs'], file_path, linenum)
+# Sort the output alphabetically by name and then by chip
+output_rows = set()
+for chip in (*CHIP_NAMES, "host", "all"):
+ if chip in chips_all_configs:
+ all_configs = chips_all_configs[chip]
+ for config_name in all_configs:
+ output_rows.add((config_name, chip))
with open(outfile, 'w', newline='') as csvfile:
- fieldnames = ('name', 'location', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
+ fieldnames = ('name', 'location', 'platform', 'chip', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', dialect='excel-tab')
writer.writeheader()
- for config_name, config_obj in sorted(all_configs.items()):
- # kinda ugly, but good enough for now without messing with TSV
- if 'docref' in config_obj['attrs']:
- desc = "{} (see <<{}>>)".format(config_obj['description'], config_obj['attrs']['docref'])
- else:
- desc = config_obj['description']
- writer.writerow({'name': config_name, 'location': '/{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'description': desc, **config_obj['attrs']})
+ for config_name, chip in sorted(output_rows):
+ config_obj = chips_all_configs[chip][config_name]
+ writer.writerow({'name': config_name, 'location': '/{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'platform': "host" if chip == "host" else "rp2", 'chip': chip if chip in CHIP_NAMES else "all", 'description': config_obj['description'], **config_obj['attrs']})
diff --git a/tools/extract_configs.py b/tools/extract_configs.py
index c95da4084..034866987 100755
--- a/tools/extract_configs.py
+++ b/tools/extract_configs.py
@@ -7,11 +7,11 @@
#
# Script to scan the Raspberry Pi Pico SDK tree searching for configuration items
# Outputs a tab separated file of the configuration item:
-# name location description type advanced default depends enumvalues group max min
+# name location platform chip description type advanced default depends enumvalues group max min
#
# Usage:
#
-# tools/extract_configs.py [output file]
+# tools/extract_configs.py [output file]
#
# If not specified, output file will be `pico_configs.tsv`
@@ -22,43 +22,66 @@
import csv
import logging
+from collections import defaultdict
+
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
scandir = sys.argv[1]
outfile = sys.argv[2] if len(sys.argv) > 2 else 'pico_configs.tsv'
-CONFIG_RE = re.compile(r'//\s+PICO_CONFIG:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$')
+BASE_CONFIG_NAME = 'PICO_CONFIG'
+BASE_CONFIG_RE = re.compile(r'\b{}\b'.format(BASE_CONFIG_NAME))
+BASE_CMAKE_CONFIG_NAME = 'PICO_CMAKE_CONFIG'
+BASE_CMAKE_CONFIG_RE = re.compile(r'\b{}\b'.format(BASE_CMAKE_CONFIG_NAME))
+BASE_BUILD_DEFINE_NAME = 'PICO_BUILD_DEFINE'
+BASE_BUILD_DEFINE_RE = re.compile(r'\b{}\b'.format(BASE_BUILD_DEFINE_NAME))
+
+CONFIG_RE = re.compile(r'//\s+{}:\s+(\w+),\s+([^,]+)(?:,\s+(.*))?$'.format(BASE_CONFIG_NAME))
DEFINE_RE = re.compile(r'#define\s+(\w+)\s+(.+?)(\s*///.*)?$')
-all_configs = {}
+ALLOWED_CONFIG_PROPERTIES = set(['type', 'default', 'min', 'max', 'enumvalues', 'group', 'advanced', 'depends'])
+
+CHIP_NAMES = ["rp2040", "rp2350"]
+
+chips_all_configs = defaultdict(dict)
all_attrs = set()
-all_descriptions = {}
-all_defines = {}
+chips_all_descriptions = defaultdict(dict)
+chips_all_defines = defaultdict(dict)
-def ValidateAttrs(config_attrs, file_path, linenum):
+def ValidateAttrs(config_name, config_attrs, file_path, linenum):
_type = config_attrs.get('type', 'int')
# Validate attrs
+ for key in config_attrs.keys():
+ if key not in ALLOWED_CONFIG_PROPERTIES:
+ raise Exception('{} at {}:{} has unexpected property "{}"'.format(config_name, file_path, linenum, key))
+
if _type == 'int':
assert 'enumvalues' not in config_attrs
_min = _max = _default = None
if config_attrs.get('min', None) is not None:
- value = config_attrs['min']
- m = re.match(r'^(\d+)e(\d+)$', value.lower())
- if m:
- _min = int(m.group(1)) * 10**int(m.group(2))
- else:
- _min = int(value, 0)
+ try:
+ value = config_attrs['min']
+ m = re.match(r'^(\d+)e(\d+)$', value.lower())
+ if m:
+ _min = int(m.group(1)) * 10**int(m.group(2))
+ else:
+ _min = int(value, 0)
+ except ValueError:
+ logger.info('{} at {}:{} has non-integer min value "{}"'.format(config_name, file_path, linenum, config_attrs['min']))
if config_attrs.get('max', None) is not None:
- value = config_attrs['max']
- m = re.match(r'^(\d+)e(\d+)$', value.lower())
- if m:
- _max = int(m.group(1)) * 10**int(m.group(2))
- else:
- _max = int(value, 0)
+ try:
+ value = config_attrs['max']
+ m = re.match(r'^(\d+)e(\d+)$', value.lower())
+ if m:
+ _max = int(m.group(1)) * 10**int(m.group(2))
+ else:
+ _max = int(value, 0)
+ except ValueError:
+ logger.info('{} at {}:{} has non-integer max value "{}"'.format(config_name, file_path, linenum, config_attrs['max']))
if config_attrs.get('default', None) is not None:
if '/' not in config_attrs['default']:
try:
@@ -69,7 +92,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
else:
_default = int(value, 0)
except ValueError:
- pass
+ logger.info('{} at {}:{} has non-integer default value "{}"'.format(config_name, file_path, linenum, config_attrs['default']))
if _min is not None and _max is not None:
if _min > _max:
raise Exception('{} at {}:{} has min {} > max {}'.format(config_name, file_path, linenum, config_attrs['min'], config_attrs['max']))
@@ -88,7 +111,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
_default = config_attrs.get('default', None)
if _default is not None:
if '/' not in _default:
- if (_default.lower() != '0') and (config_attrs['default'].lower() != '1') and ( _default not in all_configs):
+ if (_default not in ('0', '1')) and (_default not in all_config_names):
logger.info('{} at {}:{} has non-integer default value "{}"'.format(config_name, file_path, linenum, config_attrs['default']))
elif _type == 'enum':
@@ -105,7 +128,7 @@ def ValidateAttrs(config_attrs, file_path, linenum):
if _default not in _enumvalues:
raise Exception('{} at {}:{} has default value {} which isn\'t in list of enumvalues {}'.format(config_name, file_path, linenum, config_attrs['default'], config_attrs['enumvalues']))
else:
- raise Exception("Found unknown PICO_CONFIG type {} at {}:{}".format(_type, file_path, linenum))
+ raise Exception("Found unknown {} type {} at {}:{}".format(BASE_CONFIG_NAME, _type, file_path, linenum))
@@ -117,55 +140,68 @@ def ValidateAttrs(config_attrs, file_path, linenum):
file_ext = os.path.splitext(filename)[1]
if file_ext in ('.c', '.h'):
file_path = os.path.join(dirpath, filename)
+ applicable = "all"
+ for chip in (*CHIP_NAMES, "host"):
+ if "/{}/".format(chip) in dirpath:
+ applicable = chip
+ break
with open(file_path, encoding="ISO-8859-1") as fh:
linenum = 0
for line in fh.readlines():
linenum += 1
line = line.strip()
- m = CONFIG_RE.match(line)
- if m:
- config_name = m.group(1)
- config_description = m.group(2)
- _attrs = m.group(3)
- # allow commas to appear inside brackets by converting them to and from NULL chars
- _attrs = re.sub(r'(\(.+\))', lambda m: m.group(1).replace(',', '\0'), _attrs)
-
- if '=' in config_description:
- raise Exception("For {} at {}:{} the description was set to '{}' - has the description field been omitted?".format(config_name, file_path, linenum, config_description))
- if config_description in all_descriptions:
- # relax check for the same header/variable in a different tree
- if config_name != all_descriptions[config_description]['config_name'] or filename != all_descriptions[config_description]['filename_only']:
- raise Exception("Found description {} at {}:{} but it was already used at {}:{}".format(config_description, file_path, linenum, os.path.join(scandir, all_descriptions[config_description]['filename']), all_descriptions[config_description]['line_number']))
+ if BASE_CMAKE_CONFIG_RE.search(line):
+ raise Exception("Found {} at {}:{} ({}) which isn't expected in {} files".format(BASE_CMAKE_CONFIG_NAME, file_path, linenum, line, file_ext))
+ elif BASE_BUILD_DEFINE_RE.search(line):
+ raise Exception("Found {} at {}:{} ({}) which isn't expected in {} files".format(BASE_BUILD_DEFINE_NAME, file_path, linenum, line, file_ext))
+ elif BASE_CONFIG_RE.search(line):
+ m = CONFIG_RE.match(line)
+ if not m:
+ if line.startswith("//// "):
+ logger.info("Possible misformatted {} at {}:{} ({})".format(BASE_CONFIG_NAME, file_path, linenum, line))
+ else:
+ raise Exception("Found misformatted {} at {}:{} ({})".format(BASE_CONFIG_NAME, file_path, linenum, line))
else:
- all_descriptions[config_description] = {'config_name': config_name, 'filename': os.path.relpath(file_path, scandir), 'filename_only':filename, 'line_number': linenum}
-
- config_attrs = {}
- prev = None
- # Handle case where attr value contains a comma
- for item in _attrs.split(','):
- if "=" not in item:
- assert(prev)
- item = prev + "," + item
- try:
- k, v = (i.strip() for i in item.split('='))
- except ValueError:
- raise Exception('{} at {}:{} has malformed value {}'.format(config_name, file_path, linenum, item))
- config_attrs[k] = v.replace('\0', ',')
- all_attrs.add(k)
- prev = item
- #print(file_path, config_name, config_attrs)
-
- if 'group' not in config_attrs:
- raise Exception('{} at {}:{} has no group attribute'.format(config_name, file_path, linenum))
-
- #print(file_path, config_name, config_attrs)
- if config_name in all_configs:
- # relax check for the same header/variable in a different tree
- if filename != all_configs[config_name]['filename_only']:
+ config_name = m.group(1)
+ config_description = m.group(2)
+ _attrs = m.group(3)
+ # allow commas to appear inside brackets by converting them to and from NULL chars
+ _attrs = re.sub(r'(\(.+\))', lambda m: m.group(1).replace(',', '\0'), _attrs)
+
+ if '=' in config_description:
+ raise Exception("For {} at {}:{} the description was set to '{}' - has the description field been omitted?".format(config_name, file_path, linenum, config_description))
+ all_descriptions = chips_all_descriptions[applicable]
+ if config_description in all_descriptions:
+ raise Exception("Found description {} at {}:{} but it was already used at {}:{}".format(config_description, file_path, linenum, os.path.join(scandir, all_descriptions[config_description]['filename']), all_descriptions[config_description]['line_number']))
+ else:
+ all_descriptions[config_description] = {'config_name': config_name, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum}
+
+ config_attrs = {}
+ prev = None
+ # Handle case where attr value contains a comma
+ for item in _attrs.split(','):
+ if "=" not in item:
+ assert(prev)
+ item = prev + "," + item
+ try:
+ k, v = (i.strip() for i in item.split('='))
+ except ValueError:
+ raise Exception('{} at {}:{} has malformed value {}'.format(config_name, file_path, linenum, item))
+ config_attrs[k] = v.replace('\0', ',')
+ all_attrs.add(k)
+ prev = item
+ #print(file_path, config_name, config_attrs)
+
+ if 'group' not in config_attrs:
+ raise Exception('{} at {}:{} has no group attribute'.format(config_name, file_path, linenum))
+
+ #print(file_path, config_name, config_attrs)
+ all_configs = chips_all_configs[applicable]
+ if config_name in all_configs:
raise Exception("Found {} at {}:{} but it was already declared at {}:{}".format(config_name, file_path, linenum, os.path.join(scandir, all_configs[config_name]['filename']), all_configs[config_name]['line_number']))
- else:
- all_configs[config_name] = {'attrs': config_attrs, 'filename': os.path.relpath(file_path, scandir), 'filename_only' : filename, 'line_number': linenum, 'description': config_description}
+ else:
+ all_configs[config_name] = {'attrs': config_attrs, 'filename': os.path.relpath(file_path, scandir), 'line_number': linenum, 'description': config_description}
else:
m = DEFINE_RE.match(line)
if m:
@@ -180,47 +216,110 @@ def ValidateAttrs(config_attrs, file_path, linenum):
m = re.match(r'^_u\(((0x)?\d+)\)$', value.lower())
if m:
value = m.group(1)
+ all_defines = chips_all_defines[applicable]
if name not in all_defines:
all_defines[name] = dict()
if value not in all_defines[name]:
all_defines[name][value] = set()
all_defines[name][value] = (file_path, linenum)
+all_config_names = set()
+for all_configs in chips_all_configs.values():
+ all_config_names.update(all_configs.keys())
+
# Check for defines with missing PICO_CONFIG entries
-resolved_defines = dict()
-for d in all_defines:
- if d not in all_configs and d.startswith("PICO_"):
- logger.warning("Potential unmarked PICO define {}".format(d))
- # resolve "nested defines" - this allows e.g. USB_DPRAM_MAX to resolve to USB_DPRAM_SIZE which is set to 4096 (which then matches the relevant PICO_CONFIG entry)
- for val in all_defines[d]:
- if val in all_defines:
- resolved_defines[d] = all_defines[val]
-
-for config_name, config_obj in all_configs.items():
- file_path = os.path.join(scandir, config_obj['filename'])
- linenum = config_obj['line_number']
-
- ValidateAttrs(config_obj['attrs'], file_path, linenum)
-
- # Check that default values match up
- if 'default' in config_obj['attrs']:
- config_default = config_obj['attrs']['default']
- if config_name in all_defines:
- defines_obj = all_defines[config_name]
- if config_default not in defines_obj and (config_name not in resolved_defines or config_default not in resolved_defines[config_name]):
- if '/' in config_default or ' ' in config_default:
- continue
- # There _may_ be multiple matching defines, but arbitrarily display just one in the error message
- first_define_value = list(defines_obj.keys())[0]
- first_define_file_path, first_define_linenum = defines_obj[first_define_value]
- raise Exception('Found {} at {}:{} with a default of {}, but #define says {} (at {}:{})'.format(config_name, file_path, linenum, config_default, first_define_value, first_define_file_path, first_define_linenum))
- else:
- raise Exception('Found {} at {}:{} with a default of {}, but no matching #define found'.format(config_name, file_path, linenum, config_default))
+chips_resolved_defines = defaultdict(dict)
+for applicable, all_defines in chips_all_defines.items():
+ for d in all_defines:
+ if d not in all_config_names and d.startswith("PICO_"):
+ logger.warning("Potential unmarked PICO define {}".format(d))
+ resolved_defines = chips_resolved_defines[applicable]
+ # resolve "nested defines" - this allows e.g. USB_DPRAM_MAX to resolve to USB_DPRAM_SIZE which is set to 4096 (which then matches the relevant PICO_CONFIG entry)
+ for val in all_defines[d]:
+ if val in all_defines:
+ resolved_defines[d] = all_defines[val]
+
+for applicable, all_configs in chips_all_configs.items():
+ all_defines = chips_all_defines[applicable]
+ for config_name, config_obj in all_configs.items():
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
+
+ ValidateAttrs(config_name, config_obj['attrs'], file_path, linenum)
+
+ # Check that default values match up
+ if 'default' in config_obj['attrs']:
+ config_default = config_obj['attrs']['default']
+ if config_name in all_defines:
+ defines_obj = all_defines[config_name]
+ if config_default not in defines_obj and (config_name not in resolved_defines or config_default not in resolved_defines[config_name]):
+ if '/' in config_default or ' ' in config_default:
+ continue
+ # There _may_ be multiple matching defines, but arbitrarily display just one in the error message
+ first_define_value = list(defines_obj.keys())[0]
+ first_define_file_path, first_define_linenum = defines_obj[first_define_value]
+ raise Exception('Found {} at {}:{} with a default of {}, but #define says {} (at {}:{})'.format(config_name, file_path, linenum, config_default, first_define_value, first_define_file_path, first_define_linenum))
+ else:
+ raise Exception('Found {} at {}:{} with a default of {}, but no matching #define found'.format(config_name, file_path, linenum, config_default))
+
+# All settings in "host" should also be in "all"
+for config_name, config_obj in chips_all_configs["host"].items():
+ if config_name not in chips_all_configs["all"]:
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
+ raise Exception("Found 'host' config {} at {}:{}, but no matching non-host config found".format(config_name, file_path, linenum))
+
+# Any chip-specific settings should not be in "all"
+for chip in CHIP_NAMES:
+ for config_name, chip_config_obj in chips_all_configs[chip].items():
+ if config_name in chips_all_configs["all"]:
+ all_config_obj = chips_all_configs["all"][config_name]
+ chip_file_path = os.path.join(scandir, chip_config_obj['filename'])
+ chip_linenum = chip_config_obj['line_number']
+ all_file_path = os.path.join(scandir, all_config_obj['filename'])
+ all_linenum = all_config_obj['line_number']
+ raise Exception("'{}' config {} at {}:{} also found at {}:{}".format(chip, config_name, chip_file_path, chip_linenum, all_file_path, all_linenum))
+
+def build_mismatch_exception_message(name, thing, config_obj1, value1, config_obj2, value2):
+ obj1_filepath = os.path.join(scandir, config_obj1['filename'])
+ obj2_filepath = os.path.join(scandir, config_obj2['filename'])
+ return "'{}' {} mismatch at {}:{} ({}) and {}:{} ({})".format(name, thing, obj1_filepath, config_obj1['line_number'], value1, obj2_filepath, config_obj2['line_number'], value2)
+
+# Check that any identically-named setttings have appropriate matching attributes
+for applicable in chips_all_configs:
+ for other in chips_all_configs:
+ if other == applicable:
+ continue
+ for config_name, applicable_config_obj in chips_all_configs[applicable].items():
+ if config_name in chips_all_configs[other]:
+ other_config_obj = chips_all_configs[other][config_name]
+ # Check that fields match
+ for field in ['description']:
+ applicable_value = applicable_config_obj[field]
+ other_value = other_config_obj[field]
+ if applicable_value != other_value:
+ raise Exception(build_mismatch_exception_message(config_name, field, applicable_config_obj, applicable_value, other_config_obj, other_value))
+ # Check that attributes match
+ for attr in applicable_config_obj['attrs']:
+ if attr != 'default': # totally fine for defaults to vary per-platform
+ applicable_value = applicable_config_obj['attrs'][attr]
+ other_value = other_config_obj['attrs'][attr]
+ if applicable_value != other_value:
+ raise Exception(build_mismatch_exception_message(config_name, "attribute '{}'".format(attr), applicable_config_obj, applicable_value, other_config_obj, other_value))
+
+# Sort the output alphabetically by name and then by chip
+output_rows = set()
+for chip in (*CHIP_NAMES, "host", "all"):
+ if chip in chips_all_configs:
+ all_configs = chips_all_configs[chip]
+ for config_name in all_configs:
+ output_rows.add((config_name, chip))
with open(outfile, 'w', newline='') as csvfile:
- fieldnames = ('name', 'location', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
+ fieldnames = ('name', 'location', 'platform', 'chip', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', dialect='excel-tab')
writer.writeheader()
- for config_name, config_obj in sorted(all_configs.items()):
- writer.writerow({'name': config_name, 'location': '/{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'description': config_obj['description'], **config_obj['attrs']})
+ for config_name, chip in sorted(output_rows):
+ config_obj = chips_all_configs[chip][config_name]
+ writer.writerow({'name': config_name, 'location': '/{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'platform': "host" if chip == "host" else "rp2", 'chip': chip if chip in CHIP_NAMES else "all", 'description': config_obj['description'], **config_obj['attrs']})
diff --git a/tools/pioasm/CMakeLists.txt b/tools/pioasm/CMakeLists.txt
index 0106da640..a7698cd81 100644
--- a/tools/pioasm/CMakeLists.txt
+++ b/tools/pioasm/CMakeLists.txt
@@ -58,7 +58,7 @@ if (PIOASM_FLAT_INSTALL)
set(INSTALL_CONFIGDIR pioasm)
set(INSTALL_BINDIR pioasm)
else()
- set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/pioasm)
+ set(INSTALL_CONFIGDIR lib/cmake/pioasm)
set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
endif()
diff --git a/tools/pioasm/c_sdk_output.cpp b/tools/pioasm/c_sdk_output.cpp
index f54fabcd9..c1730db4c 100644
--- a/tools/pioasm/c_sdk_output.cpp
+++ b/tools/pioasm/c_sdk_output.cpp
@@ -109,7 +109,7 @@ struct c_sdk_output : public output_format {
fprintf(out, " .instructions = %sprogram_instructions,\n", prefix.c_str());
fprintf(out, " .length = %d,\n", (int) program.instructions.size());
fprintf(out, " .origin = %d,\n", program.origin.get());
- fprintf(out, " .pio_version = %d,\n", program.pio_version);
+ fprintf(out, " .pio_version = %spio_version,\n", prefix.c_str());
fprintf(out, "#if PICO_PIO_VERSION > 0\n");
fprintf(out, " .used_gpio_ranges = 0x%x\n", program.used_gpio_ranges);
fprintf(out, "#endif\n");
diff --git a/tools/pioasm/gen/parser.cpp b/tools/pioasm/gen/parser.cpp
index 7027d2165..d75e8afbe 100644
--- a/tools/pioasm/gen/parser.cpp
+++ b/tools/pioasm/gen/parser.cpp
@@ -1127,7 +1127,7 @@ namespace yy {
break;
case 22: // directive: ".in" value direction autop threshold
- { pioasm.get_current_program(yystack_[4].location, ".out", true).set_in(yylhs.location, yystack_[3].value.as < std::shared_ptr > (), yystack_[2].value.as < bool > (), yystack_[1].value.as < bool > (), yystack_[0].value.as < std::shared_ptr > ()); }
+ { pioasm.get_current_program(yystack_[4].location, ".in", true).set_in(yylhs.location, yystack_[3].value.as < std::shared_ptr > (), yystack_[2].value.as < bool > (), yystack_[1].value.as < bool > (), yystack_[0].value.as < std::shared_ptr > ()); }
break;
case 23: // directive: ".out" value direction autop threshold
@@ -1135,7 +1135,7 @@ namespace yy {
break;
case 24: // directive: ".set" value
- { pioasm.check_version(1, yylhs.location, ".in"); pioasm.get_current_program(yystack_[1].location, ".out", true).set_set_count(yylhs.location, yystack_[0].value.as < std::shared_ptr > ()); }
+ { pioasm.get_current_program(yystack_[1].location, ".set", true).set_set_count(yylhs.location, yystack_[0].value.as < std::shared_ptr > ()); }
break;
case 25: // directive: ".wrap_target"
diff --git a/tools/pioasm/parser.yy b/tools/pioasm/parser.yy
index df05f5f7d..730bc9205 100644
--- a/tools/pioasm/parser.yy
+++ b/tools/pioasm/parser.yy
@@ -199,9 +199,9 @@ directive:
| SIDE_SET value OPTIONAL { pioasm.get_current_program(@1, ".side_set", true).set_sideset(@$, $2, true, false); }
| SIDE_SET value PINDIRS { pioasm.get_current_program(@1, ".side_set", true).set_sideset(@$, $2, false, true); }
| SIDE_SET value { pioasm.get_current_program(@1, ".side_set", true).set_sideset(@$, $2, false, false); }
- | DOT_IN value direction autop threshold { pioasm.get_current_program(@1, ".out", true).set_in(@$, $2, $3, $4, $5); }
+ | DOT_IN value direction autop threshold { pioasm.get_current_program(@1, ".in", true).set_in(@$, $2, $3, $4, $5); }
| DOT_OUT value direction autop threshold { pioasm.get_current_program(@1, ".out", true).set_out(@$, $2, $3, $4, $5); }
- | DOT_SET value { pioasm.check_version(1, @$, ".in"); pioasm.get_current_program(@1, ".out", true).set_set_count(@$, $2); }
+ | DOT_SET value { pioasm.get_current_program(@1, ".set", true).set_set_count(@$, $2); }
| WRAP_TARGET { pioasm.get_current_program(@1, ".wrap_target").set_wrap_target(@$); }
| WRAP { pioasm.get_current_program(@1, ".wrap").set_wrap(@$); }
| WORD value { pioasm.get_current_program(@1, "instruction").add_instruction(std::shared_ptr(new instr_word(@$, $2))); }
diff --git a/tools/pioasm/pio_disassembler.cpp b/tools/pioasm/pio_disassembler.cpp
index eb1f4268c..2a34796d0 100644
--- a/tools/pioasm/pio_disassembler.cpp
+++ b/tools/pioasm/pio_disassembler.cpp
@@ -90,8 +90,8 @@ std::string disassemble(uint inst, uint sideset_bits_including_opt, bool sideset
invalid = true;
} else {
std::string index;
- if (arg2 & 8) index = "y";
- else index = std::to_string(arg2 & 7);
+ if (arg2 & 8) index = std::to_string(arg2 & 3);
+ else index = "y";
std::string guts = "";
op("mov");
if (arg1 & 4) {
diff --git a/tools/run_all_bazel_checks.py b/tools/run_all_bazel_checks.py
index dfdc24633..13a0656c6 100755
--- a/tools/run_all_bazel_checks.py
+++ b/tools/run_all_bazel_checks.py
@@ -6,10 +6,16 @@
#
# Runs all Bazel checks.
+import argparse
import sys
from bazel_build import build_all_configurations
-from bazel_common import setup_logging, print_framed_string, parse_common_args
+from bazel_common import (
+ setup_logging,
+ print_framed_string,
+ print_to_stderr,
+ add_common_args,
+)
from compare_build_systems import compare_build_systems
from check_source_files_in_bazel_build import check_sources_in_bazel_build
@@ -18,34 +24,55 @@ def main():
setup_logging()
failed_steps = []
- args = parse_common_args()
-
- steps = (
+ parser = argparse.ArgumentParser()
+ add_common_args(parser)
+ parser.add_argument(
+ "--program",
+ help="A program to run",
+ choices = [
+ "all",
+ "build",
+ "other",
+ ],
+ default="all",
+ )
+ args = parser.parse_args()
+ build_steps = (
{
+ "step_name": "build",
"description": "Bazel build",
"action": lambda : build_all_configurations(args.picotool_dir),
},
+ )
+ other_steps = (
{
"description": "Ensure build system configurations options match",
"action": compare_build_systems,
},
{
+ "step_name": "check_srcs_in_build",
"description": "Ensure source files are present in Bazel build",
"action": lambda : check_sources_in_bazel_build(args.picotool_dir),
},
)
+ steps_to_run = []
+ run_all_steps = args.program == "all"
+ if args.program == "build" or run_all_steps:
+ steps_to_run.extend(build_steps)
+ if args.program == "other" or run_all_steps:
+ steps_to_run.extend(other_steps)
- for step in steps:
+ for step in steps_to_run:
print_framed_string(f"{step['description']}...")
returncode = step["action"]()
if returncode != 0:
failed_steps.append(step["description"])
- print()
+ print_to_stderr()
if failed_steps:
print_framed_string("ERROR: One or more steps failed.")
for build in failed_steps:
- print(f" * FAILED: {build}")
+ print_to_stderr(f" * FAILED: {build}")
return 1
print_framed_string("All checks successfully passed!")