Add initial RP2040 Bazel build files

//examples/01_blinky builds with USB serial.

Bug: 300318025
Change-Id: I9347e5207a578f5c5c910ef12babe26c6bc179de
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/examples/+/209491
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Commit-Queue: Anthony DiGirolamo <tonymd@google.com>
diff --git a/.bazelrc b/.bazelrc
index 0b14a95..1b362fa 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -40,3 +40,7 @@
 # collisions due to a profusion of stuttering paths like
 # pw_transfer/py/pw_transfer.
 common --incompatible_default_to_explicit_init_py
+
+# Error output settings.
+common --verbose_failures
+test --test_output=errors
diff --git a/WORKSPACE b/WORKSPACE
index 0b65072..50e3ae2 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 # Load Pigweed's own dependencies that we'll need.
@@ -162,3 +163,52 @@
     strip_prefix = "cmsis_core-5.4.0_cm4",
     urls = ["https://github.com/STMicroelectronics/cmsis_core/archive/refs/tags/v5.4.0_cm4.tar.gz"],
 )
+
+git_repository(
+    name = "pico-sdk",
+    commit = "b5c6e7b068c2fedfbb1def3ec4c14e031df1a05f",
+    remote = "https://github.com/armandomontanez/pico-sdk",
+)
+
+# TODO: Provide tinyusb as a proper Bazel module.
+http_archive(
+    name = "tinyusb",
+    build_file = "@pico-sdk//src/rp2_common/tinyusb:tinyusb.BUILD",
+    sha256 = "ac57109bba00d26ffa33312d5f334990ec9a9a4d82bf890ed8b825b4610d1da2",
+    strip_prefix = "tinyusb-86c416d4c0fb38432460b3e11b08b9de76941bf5",
+    url = "https://github.com/hathach/tinyusb/archive/86c416d4c0fb38432460b3e11b08b9de76941bf5.zip",
+)
+
+# TODO(339893258): These are required because objcopy is hard-coded to the
+# toolchain tools set up by the pico-sdk.
+http_archive(
+    name = "arm_gcc_linux-x86_64",
+    build_file = "@pw_toolchain//build_external:gcc_arm_none_eabi.BUILD",
+    sha256 = "6cd1bbc1d9ae57312bcd169ae283153a9572bd6a8e4eeae2fedfbc33b115fdbb",
+    strip_prefix = "arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi",
+    url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz",
+)
+
+http_archive(
+    name = "arm_gcc_win-x86_64",
+    build_file = "@pw_toolchain//build_external:gcc_arm_none_eabi.BUILD",
+    sha256 = "51d933f00578aa28016c5e3c84f94403274ea7915539f8e56c13e2196437d18f",
+    strip_prefix = "arm-gnu-toolchain-13.2.Rel1-mingw-w64-i686-arm-none-eabi",
+    url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-mingw-w64-i686-arm-none-eabi.zip",
+)
+
+http_archive(
+    name = "arm_gcc_mac-x86_64",
+    build_file = "@pw_toolchain//build_external:gcc_arm_none_eabi.BUILD",
+    sha256 = "075faa4f3e8eb45e59144858202351a28706f54a6ec17eedd88c9fb9412372cc",
+    strip_prefix = "arm-gnu-toolchain-13.2.Rel1-darwin-x86_64-arm-none-eabi",
+    url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-darwin-x86_64-arm-none-eabi.tar.xz",
+)
+
+http_archive(
+    name = "arm_gcc_mac-aarch64",
+    build_file = "@pw_toolchain//build_external:gcc_arm_none_eabi.BUILD",
+    sha256 = "39c44f8af42695b7b871df42e346c09fee670ea8dfc11f17083e296ea2b0d279",
+    strip_prefix = "arm-gnu-toolchain-13.2.Rel1-darwin-arm64-arm-none-eabi",
+    url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-darwin-arm64-arm-none-eabi.tar.xz",
+)
diff --git a/examples/01_blinky/BUILD.bazel b/examples/01_blinky/BUILD.bazel
index 1bcd544..880afa6 100644
--- a/examples/01_blinky/BUILD.bazel
+++ b/examples/01_blinky/BUILD.bazel
@@ -13,14 +13,15 @@
 # the License.
 
 load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
-load("//targets:transition.bzl", "stm32_binary")
+load("//targets:transition.bzl", "rp2040_binary", "stm32_binary")
 
 cc_binary(
     name = "blinky",
     srcs = ["main.cc"],
     malloc = select({
-        "@platforms//cpu:armv7e-m": "@pigweed//pw_malloc",
         "//conditions:default": "@bazel_tools//tools/cpp:malloc",
+        "@pico-sdk//bazel/constraint:rp2": "@pigweed//pw_malloc",
+        "@platforms//cpu:armv7e-m": "@pigweed//pw_malloc",
     }),
     deps = [
         "//libraries/pw_board_led",
@@ -35,15 +36,21 @@
         "@pigweed//pw_system:target_hooks",
         "@pigweed//pw_system:work_queue",
     ] + select({
+        "//conditions:default": [
+            "@pigweed//targets/host_device_simulator:boot",
+        ],
+        "@pico-sdk//bazel/constraint:rp2": [
+            "@pico-sdk//src/common/pico_stdlib:pico_stdlib",
+            "@pigweed//pw_tokenizer:linker_script",
+            "@pigweed//pw_toolchain/arm_gcc:arm_none_eabi_gcc_support",
+            "@pigweed//targets/rp2040:pre_init",
+        ],
         "@platforms//cpu:armv7e-m": [
             "//targets/stm32f429i_disc1_stm32cube:linker_script",
             "@pigweed//pw_tokenizer:linker_script",
             "@pigweed//pw_toolchain/arm_gcc:arm_none_eabi_gcc_support",
             "@pigweed//targets/stm32f429i_disc1_stm32cube:pre_init",
         ],
-        "//conditions:default": [
-            "@pigweed//targets/host_device_simulator:boot",
-        ],
     }),
 )
 
@@ -54,6 +61,13 @@
     visibility = ["//tools:__pkg__"],
 )
 
+rp2040_binary(
+    name = "rp2040_blinky.elf",
+    binary = ":blinky",
+    # Visible to the flasher.
+    visibility = ["//tools:__pkg__"],
+)
+
 native_binary(
     name = "flash_stm32",
     src = "//tools:flash_device",
diff --git a/libraries/pw_board_led/BUILD.bazel b/libraries/pw_board_led/BUILD.bazel
index fd9df26..d7639f7 100644
--- a/libraries/pw_board_led/BUILD.bazel
+++ b/libraries/pw_board_led/BUILD.bazel
@@ -32,6 +32,7 @@
     actual = select({
         "//libraries/pw_board_led_host:backend_constraint_value": "//libraries/pw_board_led_host",
         "//libraries/pw_board_led_stm32f429i_disc1:backend_constraint_value": "//libraries/pw_board_led_stm32f429i_disc1",
+        "//libraries/pw_board_led_rp2040:backend_constraint_value": "//libraries/pw_board_led_rp2040",
         "//conditions:default": ":unspecified_backend",
     }),
 )
diff --git a/libraries/pw_board_led_rp2040/BUILD.bazel b/libraries/pw_board_led_rp2040/BUILD.bazel
new file mode 100644
index 0000000..148b6f0
--- /dev/null
+++ b/libraries/pw_board_led_rp2040/BUILD.bazel
@@ -0,0 +1,32 @@
+# Copyright 2024 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+package(default_visibility = ["//visibility:public"])
+
+constraint_value(
+    name = "backend_constraint_value",
+    constraint_setting = "//libraries/pw_board_led:pw_board_led_constraint_setting",
+)
+
+cc_library(
+    name = "pw_board_led_rp2040",
+    srcs = ["led.cc"],
+    target_compatible_with = [":backend_constraint_value"],
+    deps = [
+        "//libraries/pw_board_led:pw_board_led.facade",
+        "@pico-sdk//src/common/pico_stdlib:pico_stdlib",
+        "@pico-sdk//src/rp2_common/hardware_gpio:hardware_gpio",
+        "@pigweed//pw_log",
+    ],
+)
diff --git a/targets/rp2040/BUILD.bazel b/targets/rp2040/BUILD.bazel
new file mode 100644
index 0000000..9727547
--- /dev/null
+++ b/targets/rp2040/BUILD.bazel
@@ -0,0 +1,35 @@
+# Copyright 2024 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+package(default_visibility = ["//visibility:public"])
+
+platform(
+    name = "platform",
+    constraint_values = [
+        "//libraries/pw_board_led_rp2040:backend_constraint_value",
+        "@freertos//:port_ARM_CM0",
+        "@freertos//:disable_task_statics",
+        "@pico-sdk//bazel/constraint:rp2",
+        "@pico-sdk//bazel/constraint:rp2040",
+        "@pico-sdk//bazel/constraint:stdio_usb",
+        "@pigweed//targets/rp2040:freertos_config_cv",
+        "@pigweed//pw_build/constraints/rtos:freertos",
+        "@pigweed//pw_interrupt_cortex_m:backend",
+        "@pigweed//pw_malloc_freelist:backend",
+        "@pigweed//pw_sys_io_rp2040:backend",
+        # For toolchain selection.
+        "@platforms//cpu:armv6-m",
+        "@pw_toolchain//constraints/arm_mcpu:cortex-m0",
+    ],
+)
diff --git a/targets/transition.bzl b/targets/transition.bzl
index b6d2d8d..ec6e9c2 100644
--- a/targets/transition.bzl
+++ b/targets/transition.bzl
@@ -43,13 +43,13 @@
     ],
 )
 
-def _binary_impl(ctx):
+def _stm32_binary_impl(ctx):
     out = ctx.actions.declare_file(ctx.label.name)
     ctx.actions.symlink(output = out, target_file = ctx.executable.binary)
     return [DefaultInfo(files = depset([out]), executable = out)]
 
 stm32_binary = rule(
-    _binary_impl,
+    _stm32_binary_impl,
     attrs = {
         "binary": attr.label(
             doc = "cc_binary to build for stm32f429i_disc1_stm32cube.",
@@ -63,3 +63,46 @@
     },
     doc = "Builds the specified binary for the stm32f429i_disc1_stm32cube platform.",
 )
+
+def _rp2040_transition_impl(settings, attr):
+    # buildifier: disable=unused-variable
+    _ignore = settings, attr
+
+    return {
+        "//command_line_option:platforms": "//targets/rp2040:platform",
+        "@pigweed//pw_log:backend_impl": "@pigweed//pw_log_tokenized:impl",
+        "@pigweed//pw_log:backend": "@pigweed//pw_log_tokenized",
+        "@pigweed//pw_log_tokenized:handler_backend": "@pigweed//pw_system:log_backend",
+    }
+
+_rp2040_transition = transition(
+    implementation = _rp2040_transition_impl,
+    inputs = [],
+    outputs = [
+        "//command_line_option:platforms",
+        "@pigweed//pw_log:backend_impl",
+        "@pigweed//pw_log:backend",
+        "@pigweed//pw_log_tokenized:handler_backend",
+    ],
+)
+
+def _rp2040_binary_impl(ctx):
+    out = ctx.actions.declare_file(ctx.label.name)
+    ctx.actions.symlink(output = out, target_file = ctx.executable.binary)
+    return [DefaultInfo(files = depset([out]), executable = out)]
+
+rp2040_binary = rule(
+    _rp2040_binary_impl,
+    attrs = {
+        "binary": attr.label(
+            doc = "cc_binary to build for rp2040 using pico-sdk.",
+            cfg = _rp2040_transition,
+            executable = True,
+            mandatory = True,
+        ),
+        "_allowlist_function_transition": attr.label(
+            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+        ),
+    },
+    doc = "Builds the specified binary for the pico-sdk rp2040 platform.",
+)
diff --git a/third_party/pigweed b/third_party/pigweed
index cd07cc1..624978e 160000
--- a/third_party/pigweed
+++ b/third_party/pigweed
@@ -1 +1 @@
-Subproject commit cd07cc170ebc110e88caede07826bfe99c61fb8a
+Subproject commit 624978e6fb2f4fe3dd96a0af64860334a5bbd844
diff --git a/tools/sample_project_tools/build_project.py b/tools/sample_project_tools/build_project.py
index 704a739..a5325a0 100644
--- a/tools/sample_project_tools/build_project.py
+++ b/tools/sample_project_tools/build_project.py
@@ -55,6 +55,8 @@
         '--export-compile-commands',
     ]
 
+    default_bazel_targets = ['//...:all']
+
     build_recipes = [
         BuildRecipe(
             build_dir=Path('out/gn'),
@@ -77,6 +79,19 @@
                 ),
             ],
         ),
+        BuildRecipe(
+            build_dir=Path('out/bazel'),
+            title='bazel',
+            steps=[
+                BuildCommand(
+                    build_system_command='bazel',
+                    build_system_extra_args=[
+                        'build',
+                    ],
+                    targets=default_bazel_targets,
+                ),
+            ],
+        ),
     ]
 
     # This project doesn't pass forward presubmit steps as they introduce some