Add basic rpi2040 blink demo app

Phew, things build!  Lets check in how far we got.

Change-Id: Id82e2f4c73eed6620b2b4661726f931e79a6b0c1
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/.bazelrc b/.bazelrc
index 8290da4..53f34e8 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -22,6 +22,7 @@
 build:roborio --platforms=//tools/platforms:linux_roborio
 build:armhf-debian --platforms=//tools/platforms:linux_armhf
 build:cortex-m4f --platforms=//tools/platforms:cortex_m4f
+build:rp2040 --platforms=//tools/platforms:rp2040
 
 # Without this, we end up rebuilding from scratch every time we change compilers.  This is needed to make --cpu work (even though it shouldn't be used).
 build --crosstool_top=@//tools/cpp:toolchain --host_crosstool_top=@//tools/cpp:toolchain
diff --git a/WORKSPACE b/WORKSPACE
index d532887..8a49b63 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -123,6 +123,7 @@
     "//tools/cpp:cc-toolchain-armhf-debian",
     "//tools/cpp:cc-toolchain-roborio",
     "//tools/cpp:cc-toolchain-cortex-m4f",
+    "//tools/cpp:cc-toolchain-rp2040",
     # Find a good way to select between these two M4F toolchains.
     #"//tools/cpp:cc-toolchain-cortex-m4f-k22",
     "//tools/python:python_toolchain",
diff --git a/debian/gstreamer.BUILD b/debian/gstreamer.BUILD
index 7c3e569..205db5a 100644
--- a/debian/gstreamer.BUILD
+++ b/debian/gstreamer.BUILD
@@ -160,6 +160,7 @@
             "usr/lib/arm-linux-gnueabihf/libxml2.so.2",
         ],
         "cortex-m": [],
+        "cortex-m0plus": [],
     }),
     hdrs = glob([
         "usr/lib/x86_64-linux-gnu/glib-2.0/include/**/*.h",
@@ -180,10 +181,9 @@
             "usr/include/glib-2.0",
             "usr/include/gstreamer-1.0",
         ],
-        "roborio": [
-        ],
-        "cortex-m": [
-        ],
+        "roborio": [],
+        "cortex-m": [],
+        "cortex-m0plus": [],
     }),
     linkopts = [
         "-ldl",
diff --git a/debian/opencv.BUILD b/debian/opencv.BUILD
index 56b3cac..32ecec2 100644
--- a/debian/opencv.BUILD
+++ b/debian/opencv.BUILD
@@ -472,6 +472,7 @@
             "usr/lib/arm-linux-gnueabihf/libgomp.so.1",
         ],
         "cortex-m": [],
+        "cortex-m0plus": [],
     }),
     hdrs = glob([
         "usr/include/opencv/**",
diff --git a/frc971/imu/BUILD b/frc971/imu/BUILD
new file mode 100644
index 0000000..f386da4
--- /dev/null
+++ b/frc971/imu/BUILD
@@ -0,0 +1,25 @@
+load("//third_party/pico-sdk:hex.bzl", "uf2_from_elf")
+
+# TODO(austin): We should be able to either push the linker script into the crosstool, or wrap this in a macro.
+cc_binary(
+    name = "blink.elf",
+    srcs = [
+        "blink.c",
+        "//third_party/pico-sdk/src/rp2_common/boot_stage2:bs2_default_padded_checksummed.S",
+    ],
+    additional_linker_inputs = [
+        "//third_party/pico-sdk:src/rp2_common/pico_standard_link/memmap_default.ld",
+    ],
+    linkopts = [
+        "-Wl,--script=third_party/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld",
+    ],
+    target_compatible_with = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m0plus",
+    ],
+    deps = ["//third_party/pico-sdk"],
+)
+
+uf2_from_elf(
+    name = "blink",
+)
diff --git a/frc971/imu/blink.c b/frc971/imu/blink.c
new file mode 100644
index 0000000..d478d78
--- /dev/null
+++ b/frc971/imu/blink.c
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/stdlib.h"
+
+int main() {
+#ifndef PICO_DEFAULT_LED_PIN
+#warning blink example requires a board with a regular LED
+#else
+    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
+    gpio_init(LED_PIN);
+    gpio_set_dir(LED_PIN, GPIO_OUT);
+    while (true) {
+        gpio_put(LED_PIN, 1);
+        sleep_ms(250);
+        gpio_put(LED_PIN, 0);
+        sleep_ms(250);
+    }
+#endif
+}
diff --git a/motors/core/BUILD b/motors/core/BUILD
index d5e7cca..9d9687f 100644
--- a/motors/core/BUILD
+++ b/motors/core/BUILD
@@ -21,7 +21,10 @@
         "reg_debug.h",
         "time.h",
     ],
-    target_compatible_with = ["@platforms//os:none"],
+    target_compatible_with = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m4f",
+    ],
     visibility = ["//visibility:public"],
 )
 
@@ -30,7 +33,10 @@
     hdrs = [
         "semihosting.h",
     ],
-    target_compatible_with = ["@platforms//os:none"],
+    target_compatible_with = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m4f",
+    ],
     visibility = ["//visibility:public"],
     deps = [
         "//third_party/GSL",
@@ -45,7 +51,10 @@
     hdrs = [
         "itm.h",
     ],
-    target_compatible_with = ["@platforms//os:none"],
+    target_compatible_with = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m4f",
+    ],
     visibility = ["//visibility:public"],
     deps = [
         ":core",
diff --git a/platform_mappings b/platform_mappings
index 04265dd..718ca72 100644
--- a/platform_mappings
+++ b/platform_mappings
@@ -12,6 +12,9 @@
   //tools/platforms:cortex_m4f
     --cpu=cortex-m4f
 
+  //tools/platforms:rp2040
+    --cpu=rp2040
+
 flags:
   --cpu=k8
     //tools/platforms:linux_x86
@@ -24,3 +27,6 @@
 
   --cpu=cortex-m4f
     //tools/platforms:cortex_m4f
+
+  --cpu=rp2040
+    //tools/platforms:rp2040
diff --git a/third_party/pico-sdk/BUILD b/third_party/pico-sdk/BUILD
new file mode 100644
index 0000000..ab6ff56
--- /dev/null
+++ b/third_party/pico-sdk/BUILD
@@ -0,0 +1,420 @@
+exports_files(["src/rp2_common/pico_standard_link/memmap_default.ld"])
+
+cc_library(
+    name = "pico-sdk",
+    srcs = [
+        "src/common/pico_sync/critical_section.c",
+        "src/common/pico_sync/lock_core.c",
+        "src/common/pico_sync/mutex.c",
+        "src/common/pico_sync/sem.c",
+        "src/common/pico_time/time.c",
+        "src/common/pico_time/timeout_helper.c",
+        "src/common/pico_util/datetime.c",
+        "src/common/pico_util/pheap.c",
+        "src/common/pico_util/queue.c",
+        "src/rp2_common/hardware_claim/claim.c",
+        "src/rp2_common/hardware_clocks/clocks.c",
+        "src/rp2_common/hardware_divider/divider.S",
+        "src/rp2_common/hardware_gpio/gpio.c",
+        "src/rp2_common/hardware_irq/irq.c",
+        "src/rp2_common/hardware_irq/irq_handler_chain.S",
+        "src/rp2_common/hardware_pll/pll.c",
+        "src/rp2_common/hardware_sync/sync.c",
+        "src/rp2_common/hardware_timer/timer.c",
+        "src/rp2_common/hardware_uart/uart.c",
+        "src/rp2_common/hardware_vreg/vreg.c",
+        "src/rp2_common/hardware_watchdog/watchdog.c",
+        "src/rp2_common/hardware_xosc/xosc.c",
+        "src/rp2_common/pico_bit_ops/bit_ops_aeabi.S",
+        "src/rp2_common/pico_bootrom/bootrom.c",
+        "src/rp2_common/pico_divider/divider.S",
+        "src/rp2_common/pico_double/double_aeabi.S",
+        "src/rp2_common/pico_double/double_init_rom.c",
+        "src/rp2_common/pico_double/double_math.c",
+        "src/rp2_common/pico_double/double_v1_rom_shim.S",
+        "src/rp2_common/pico_float/float_aeabi.S",
+        "src/rp2_common/pico_float/float_init_rom.c",
+        "src/rp2_common/pico_float/float_math.c",
+        "src/rp2_common/pico_float/float_v1_rom_shim.S",
+        "src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S",
+        "src/rp2_common/pico_malloc/pico_malloc.c",
+        "src/rp2_common/pico_mem_ops/mem_ops_aeabi.S",
+        "src/rp2_common/pico_platform/platform.c",
+        "src/rp2_common/pico_printf/printf.c",
+        "src/rp2_common/pico_runtime/runtime.c",
+        "src/rp2_common/pico_standard_link/binary_info.c",
+        "src/rp2_common/pico_standard_link/crt0.S",
+        "src/rp2_common/pico_standard_link/new_delete.cpp",
+        "src/rp2_common/pico_stdio/stdio.c",
+        "src/rp2_common/pico_stdio_uart/stdio_uart.c",
+        "src/rp2_common/pico_stdlib/stdlib.c",
+        #"src/common/pico_util/doc.h",
+    ],
+    hdrs = [
+        "src/boards/include/boards/pico.h",
+        "src/common/pico_base/include/pico.h",
+        "src/common/pico_base/include/pico/assert.h",
+        "src/common/pico_base/include/pico/config.h",
+        "src/common/pico_base/include/pico/config_autogen.h",
+        "src/common/pico_base/include/pico/error.h",
+        "src/common/pico_base/include/pico/types.h",
+        "src/common/pico_base/include/pico/version.h",
+        "src/common/pico_binary_info/include/pico/binary_info.h",
+        "src/common/pico_binary_info/include/pico/binary_info/code.h",
+        "src/common/pico_binary_info/include/pico/binary_info/defs.h",
+        "src/common/pico_binary_info/include/pico/binary_info/structure.h",
+        "src/common/pico_stdlib/include/pico/stdlib.h",
+        "src/common/pico_sync/include/pico/critical_section.h",
+        "src/common/pico_sync/include/pico/lock_core.h",
+        "src/common/pico_sync/include/pico/mutex.h",
+        "src/common/pico_sync/include/pico/sem.h",
+        "src/common/pico_sync/include/pico/sync.h",
+        "src/common/pico_time/include/pico/time.h",
+        "src/common/pico_time/include/pico/timeout_helper.h",
+        "src/common/pico_util/include/pico/util/datetime.h",
+        "src/common/pico_util/include/pico/util/pheap.h",
+        "src/common/pico_util/include/pico/util/queue.h",
+        "src/rp2040/hardware_regs/include/hardware/platform_defs.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/adc.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/addressmap.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/busctrl.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/clocks.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/dma.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/dreq.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/i2c.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/intctrl.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/io_bank0.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/io_qspi.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/m0plus.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/pads_bank0.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/pads_qspi.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/pio.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/pll.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/psm.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/pwm.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/resets.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/rosc.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/rtc.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/sio.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/spi.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/ssi.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/syscfg.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/sysinfo.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/tbman.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/timer.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/uart.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/usb.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/usb_device_dpram.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/vreg_and_chip_reset.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/watchdog.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/xip.h",
+        "src/rp2040/hardware_regs/include/hardware/regs/xosc.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/adc.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/bus_ctrl.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/clocks.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/dma.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/i2c.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/interp.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/iobank0.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/ioqspi.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/mpu.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/pads_qspi.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/padsbank0.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/pio.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/pll.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/psm.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/pwm.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/resets.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/rosc.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/rtc.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/scb.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/sio.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/spi.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/ssi.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/syscfg.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/systick.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/timer.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/uart.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/usb.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/vreg_and_chip_reset.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/watchdog.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/xip_ctrl.h",
+        "src/rp2040/hardware_structs/include/hardware/structs/xosc.h",
+        "src/rp2_common/cmsis/include/cmsis/rename_exceptions.h",
+        "src/rp2_common/hardware_base/include/hardware/address_mapped.h",
+        "src/rp2_common/hardware_claim/include/hardware/claim.h",
+        "src/rp2_common/hardware_clocks/include/hardware/clocks.h",
+        "src/rp2_common/hardware_divider/include/hardware/divider.h",
+        "src/rp2_common/hardware_divider/include/hardware/divider_helper.S",
+        "src/rp2_common/hardware_gpio/include/hardware/gpio.h",
+        "src/rp2_common/hardware_irq/include/hardware/irq.h",
+        "src/rp2_common/hardware_pll/include/hardware/pll.h",
+        "src/rp2_common/hardware_resets/include/hardware/resets.h",
+        "src/rp2_common/hardware_sync/include/hardware/sync.h",
+        "src/rp2_common/hardware_timer/include/hardware/timer.h",
+        "src/rp2_common/hardware_uart/include/hardware/uart.h",
+        "src/rp2_common/hardware_vreg/include/hardware/vreg.h",
+        "src/rp2_common/hardware_watchdog/include/hardware/watchdog.h",
+        "src/rp2_common/hardware_xosc/include/hardware/xosc.h",
+        "src/rp2_common/pico_bootrom/include/pico/bootrom.h",
+        "src/rp2_common/pico_bootrom/include/pico/bootrom/sf_table.h",
+        "src/rp2_common/pico_double/include/pico/double.h",
+        "src/rp2_common/pico_float/include/pico/float.h",
+        "src/rp2_common/pico_int64_ops/include/pico/int64_ops.h",
+        "src/rp2_common/pico_malloc/include/pico/malloc.h",
+        "src/rp2_common/pico_mem_ops/include/pico/mem_ops.h",
+        "src/rp2_common/pico_platform/include/pico/asm_helper.S",
+        "src/rp2_common/pico_platform/include/pico/platform.h",
+        "src/rp2_common/pico_printf/include/pico/printf.h",
+        "src/rp2_common/pico_runtime/include/pico/runtime.h",
+        "src/rp2_common/pico_stdio/include/pico/stdio.h",
+        "src/rp2_common/pico_stdio/include/pico/stdio/driver.h",
+        "src/rp2_common/pico_stdio_uart/include/pico/stdio_uart.h",
+    ],
+    copts = [
+        "-Wno-unused-function",
+    ],
+    defines = [
+        "LIB_PICO_BIT_OPS=1",
+        "LIB_PICO_BIT_OPS_PICO=1",
+        "LIB_PICO_DIVIDER=1",
+        "LIB_PICO_DIVIDER_HARDWARE=1",
+        "LIB_PICO_DOUBLE=1",
+        "LIB_PICO_DOUBLE_PICO=1",
+        "LIB_PICO_FLOAT=1",
+        "LIB_PICO_FLOAT_PICO=1",
+        "LIB_PICO_INT64_OPS=1",
+        "LIB_PICO_INT64_OPS_PICO=1",
+        "LIB_PICO_MALLOC=1",
+        "LIB_PICO_MEM_OPS=1",
+        "LIB_PICO_MEM_OPS_PICO=1",
+        "LIB_PICO_PLATFORM=1",
+        "LIB_PICO_PRINTF=1",
+        "LIB_PICO_PRINTF_PICO=1",
+        "LIB_PICO_RUNTIME=1",
+        "LIB_PICO_STANDARD_LINK=1",
+        "LIB_PICO_STDIO=1",
+        "LIB_PICO_STDIO_UART=1",
+        "LIB_PICO_STDLIB=1",
+        "LIB_PICO_SYNC=1",
+        "LIB_PICO_SYNC_CORE=1",
+        "LIB_PICO_SYNC_CRITICAL_SECTION=1",
+        "LIB_PICO_SYNC_MUTEX=1",
+        "LIB_PICO_SYNC_SEM=1",
+        "LIB_PICO_TIME=1",
+        "LIB_PICO_UTIL=1",
+        "PICO_COPY_TO_RAM=0",
+        "PICO_CXX_ENABLE_EXCEPTIONS=0",
+        "PICO_NO_FLASH=0",
+        "PICO_USE_BLOCKED_RAM=0",
+    ],
+    includes = [
+        "src/boards/include",
+        "src/common/pico_base/include",
+        "src/common/pico_binary_info/include",
+        "src/common/pico_stdlib/include",
+        "src/common/pico_sync/include",
+        "src/common/pico_time/include",
+        "src/common/pico_util/include",
+        "src/rp2040/hardware_regs/include",
+        "src/rp2040/hardware_structs/include",
+        "src/rp2_common/cmsis/include",
+        "src/rp2_common/hardware_base/include",
+        "src/rp2_common/hardware_claim/include",
+        "src/rp2_common/hardware_clocks/include",
+        "src/rp2_common/hardware_divider/include",
+        "src/rp2_common/hardware_gpio/include",
+        "src/rp2_common/hardware_irq/include",
+        "src/rp2_common/hardware_pll/include",
+        "src/rp2_common/hardware_resets/include",
+        "src/rp2_common/hardware_sync/include",
+        "src/rp2_common/hardware_timer/include",
+        "src/rp2_common/hardware_uart/include",
+        "src/rp2_common/hardware_vreg/include",
+        "src/rp2_common/hardware_watchdog/include",
+        "src/rp2_common/hardware_xosc/include",
+        "src/rp2_common/pico_bootrom/include",
+        "src/rp2_common/pico_double/include",
+        "src/rp2_common/pico_float/include",
+        "src/rp2_common/pico_int64_ops/include",
+        "src/rp2_common/pico_malloc/include",
+        "src/rp2_common/pico_mem_ops/include",
+        "src/rp2_common/pico_platform/include",
+        "src/rp2_common/pico_printf/include",
+        "src/rp2_common/pico_runtime/include",
+        "src/rp2_common/pico_stdio/include",
+        "src/rp2_common/pico_stdio_uart/include",
+    ],
+    linkopts = [
+        "-Wl,--wrap=" + fn
+        for fn in [
+            "sprintf",
+            "snprintf",
+            "vsnprintf",
+            "__clzsi2",
+            "__clzdi2",
+            "__ctzsi2",
+            "__ctzdi2",
+            "__popcountsi2",
+            "__popcountdi2",
+            "__clz",
+            "__clzl",
+            "__clzll",
+            "__aeabi_idiv",
+            "__aeabi_idivmod",
+            "__aeabi_ldivmod",
+            "__aeabi_uidiv",
+            "__aeabi_uidivmod",
+            "__aeabi_uldivmod",
+            "__aeabi_dadd",
+            "__aeabi_ddiv",
+            "__aeabi_dmul",
+            "__aeabi_drsub",
+            "__aeabi_dsub",
+            "__aeabi_cdcmpeq",
+            "__aeabi_cdrcmple",
+            "__aeabi_cdcmple",
+            "__aeabi_dcmpeq",
+            "__aeabi_dcmplt",
+            "__aeabi_dcmple",
+            "__aeabi_dcmpge",
+            "__aeabi_dcmpgt",
+            "__aeabi_dcmpun",
+            "__aeabi_i2d",
+            "__aeabi_l2d",
+            "__aeabi_ui2d",
+            "__aeabi_ul2d",
+            "__aeabi_d2iz",
+            "__aeabi_d2lz",
+            "__aeabi_d2uiz",
+            "__aeabi_d2ulz",
+            "__aeabi_d2f",
+            "sqrt",
+            "cos",
+            "sin",
+            "tan",
+            "atan2",
+            "exp",
+            "log",
+            "ldexp",
+            "copysign",
+            "trunc",
+            "floor",
+            "ceil",
+            "round",
+            "sincos",
+            "asin",
+            "acos",
+            "atan",
+            "sinh",
+            "cosh",
+            "tanh",
+            "asinh",
+            "acosh",
+            "atanh",
+            "exp2",
+            "log2",
+            "exp10",
+            "log10",
+            "pow",
+            "powint",
+            "hypot",
+            "cbrt",
+            "fmod",
+            "drem",
+            "remainder",
+            "remquo",
+            "expm1",
+            "log1p",
+            "fma",
+            "__aeabi_lmul",
+            "__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",
+            "sincosf",
+            "asinf",
+            "acosf",
+            "atanf",
+            "sinhf",
+            "coshf",
+            "tanhf",
+            "asinhf",
+            "acoshf",
+            "atanhf",
+            "exp2f",
+            "log2f",
+            "exp10f",
+            "log10f",
+            "powf",
+            "powintf",
+            "hypotf",
+            "cbrtf",
+            "fmodf",
+            "dremf",
+            "remainderf",
+            "remquof",
+            "expm1f",
+            "log1pf",
+            "fmaf",
+            "malloc",
+            "calloc",
+            "free",
+            "memcpy",
+            "memset",
+            "__aeabi_memcpy",
+            "__aeabi_memset",
+            "__aeabi_memcpy4",
+            "__aeabi_memset4",
+            "__aeabi_memcpy8",
+            "__aeabi_memset8",
+            "printf",
+            "vprintf",
+            "puts",
+            "putchar",
+            "getchar",
+        ]
+    ] + [
+        "-Wl,-z,max-page-size=4096",
+    ],
+    target_compatible_with = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m0plus",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third_party/pico-sdk/src/rp2_common/boot_stage2:boot_stage2_header",
+    ],
+)
diff --git a/third_party/pico-sdk/hex.bzl b/third_party/pico-sdk/hex.bzl
new file mode 100644
index 0000000..5e9dfae
--- /dev/null
+++ b/third_party/pico-sdk/hex.bzl
@@ -0,0 +1,25 @@
+def bin_from_elf(name, target_compatible_with = None):
+    native.genrule(
+        name = name,
+        srcs = ["%s.elf" % name],
+        outs = ["%s.bin" % name],
+        cmd = "$(OBJCOPY) -Obinary $< $@",
+        executable = True,
+        output_to_bindir = True,
+        target_compatible_with = target_compatible_with,
+        toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"],
+    )
+
+def uf2_from_elf(name, target_compatible_with = None):
+    native.genrule(
+        name = name,
+        srcs = ["%s.elf" % name],
+        outs = ["%s.uf2" % name],
+        cmd = "$(location //third_party/pico-sdk/tools/elf2uf2) $< $@",
+        executable = True,
+        output_to_bindir = True,
+        target_compatible_with = target_compatible_with,
+        tools = [
+            "//third_party/pico-sdk/tools/elf2uf2",
+        ],
+    )
diff --git a/third_party/pico-sdk/src/common/boot_uf2/BUILD b/third_party/pico-sdk/src/common/boot_uf2/BUILD
new file mode 100644
index 0000000..771afa6
--- /dev/null
+++ b/third_party/pico-sdk/src/common/boot_uf2/BUILD
@@ -0,0 +1,8 @@
+cc_library(
+    name = "boot_uf2",
+    hdrs = [
+        "include/boot/uf2.h",
+    ],
+    includes = ["include"],
+    visibility = ["//visibility:public"],
+)
diff --git a/third_party/pico-sdk/src/common/pico_base/include/pico/config_autogen.h b/third_party/pico-sdk/src/common/pico_base/include/pico/config_autogen.h
new file mode 100644
index 0000000..d12198d
--- /dev/null
+++ b/third_party/pico-sdk/src/common/pico_base/include/pico/config_autogen.h
@@ -0,0 +1,11 @@
+// AUTOGENERATED FROM PICO_CONFIG_HEADER_FILES and then PICO_<PLATFORM>_CONFIG_HEADER_FILES
+// DO NOT EDIT!
+
+
+// based on PICO_CONFIG_HEADER_FILES:
+
+#include "third_party/pico-sdk/src/boards/include/boards/pico.h"
+
+// based on PICO_RP2040_CONFIG_HEADER_FILES:
+
+#include "third_party/pico-sdk/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h"
diff --git a/third_party/pico-sdk/src/common/pico_base/include/pico/version.h b/third_party/pico-sdk/src/common/pico_base/include/pico/version.h
new file mode 100644
index 0000000..96e417b
--- /dev/null
+++ b/third_party/pico-sdk/src/common/pico_base/include/pico/version.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// ---------------------------------------
+// THIS FILE IS AUTOGENERATED; DO NOT EDIT
+// ---------------------------------------
+
+#ifndef _PICO_VERSION_H
+#define _PICO_VERSION_H
+
+#define PICO_SDK_VERSION_MAJOR    1
+#define PICO_SDK_VERSION_MINOR    3
+#define PICO_SDK_VERSION_REVISION 0
+#define PICO_SDK_VERSION_STRING   "1.3.0"
+
+#endif
diff --git a/third_party/pico-sdk/src/rp2_common/boot_stage2/BUILD b/third_party/pico-sdk/src/rp2_common/boot_stage2/BUILD
new file mode 100644
index 0000000..c8fc22d
--- /dev/null
+++ b/third_party/pico-sdk/src/rp2_common/boot_stage2/BUILD
@@ -0,0 +1,67 @@
+load("//third_party/pico-sdk:hex.bzl", "bin_from_elf")
+
+cc_library(
+    name = "boot_stage2_header",
+    hdrs = [
+        "asminclude/boot2_helpers/exit_from_boot2.S",
+        "asminclude/boot2_helpers/read_flash_sreg.S",
+        "asminclude/boot2_helpers/wait_ssi_ready.S",
+        "include/boot_stage2/config.h",
+    ],
+    includes = [
+        "asminclude",
+        "include",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "boot_stage2",
+    hdrs = [
+        "boot2_w25q080.S",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":boot_stage2_header",
+        # This is probably too much, but the resulting binary is bitwise identical, so what can I complain about.
+        "//third_party/pico-sdk",
+    ],
+)
+
+cc_binary(
+    name = "bs2_default.elf",
+    srcs = [
+        "compile_time_choice.S",
+    ],
+    additional_linker_inputs = ["boot_stage2.ld"],
+    linkopts = [
+        "-Wl,--script=third_party/pico-sdk/src/rp2_common/boot_stage2/boot_stage2.ld",
+    ],
+    deps = ["boot_stage2"],
+)
+
+bin_from_elf(
+    name = "bs2_default",
+)
+
+genrule(
+    name = "pad_checksum_python_rename",
+    srcs = ["pad_checksum"],
+    outs = ["pad_checksum.py"],
+    cmd = "cp -f $(SRCS) $(OUTS)",
+)
+
+py_binary(
+    name = "pad_checksum_python",
+    srcs = ["pad_checksum.py"],
+    main = "pad_checksum.py",
+)
+
+genrule(
+    name = "gen_bs2_default_padded_checksummed.S",
+    srcs = ["bs2_default.bin"],
+    outs = ["bs2_default_padded_checksummed.S"],
+    cmd = "$(location :pad_checksum_python) -s 0xffffffff $(SRCS) $(OUTS)",
+    tools = [":pad_checksum_python"],
+    visibility = ["//visibility:public"],
+)
diff --git a/third_party/pico-sdk/tools/BUILD b/third_party/pico-sdk/tools/BUILD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/pico-sdk/tools/BUILD
diff --git a/third_party/pico-sdk/tools/elf2uf2/BUILD b/third_party/pico-sdk/tools/elf2uf2/BUILD
new file mode 100644
index 0000000..98b8209
--- /dev/null
+++ b/third_party/pico-sdk/tools/elf2uf2/BUILD
@@ -0,0 +1,19 @@
+cc_binary(
+    name = "elf2uf2",
+    srcs = [
+        "elf.h",
+        "main.cpp",
+    ],
+    copts = [
+        "-Wno-format-nonliteral",
+        "-Wno-reorder",
+        "-Wno-unused-parameter",
+        "-Wno-unused-function",
+    ],
+    includes = ["."],
+    target_compatible_with = ["@platforms//os:linux"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third_party/pico-sdk/src/common/boot_uf2",
+    ],
+)
diff --git a/tools/BUILD b/tools/BUILD
index 3acd443..2e470fa 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -34,6 +34,11 @@
     constraint_values = ["@//tools/platforms/hardware:cortex_m4f"],
 )
 
+config_setting(
+    name = "cpu_cortex_m0plus",
+    constraint_values = ["@//tools/platforms/hardware:cortex_m0plus"],
+)
+
 # TODO(phil): Re-enable this with proper support.
 #config_setting(
 #    name = "cpu_cortex_m4f_k22",
diff --git a/tools/build_rules/select.bzl b/tools/build_rules/select.bzl
index 23addf5..cdeeb25 100644
--- a/tools/build_rules/select.bzl
+++ b/tools/build_rules/select.bzl
@@ -8,6 +8,7 @@
     "roborio",
     "armhf",
     "cortex-m",
+    "cortex-m0plus",
 ]
 
 """All of the CPUs we know about."""
@@ -31,6 +32,7 @@
         new_values["armhf"] = values["arm"]
         new_values["roborio"] = values["arm"]
         new_values["cortex-m"] = values["arm"]
+        new_values["cortex-m0plus"] = values["arm"]
         values = new_values
     for cpu in all_cpus:
         if cpu not in values:
@@ -46,6 +48,7 @@
         "@//tools:cpu_roborio": values["roborio"],
         "@//tools:cpu_armhf": values["armhf"],
         "@//tools:cpu_cortex_m4f": values["cortex-m"],
+        "@//tools:cpu_cortex_m0plus": values["cortex-m0plus"],
         # TODO(phil): Support this properly.
         #"@//tools:cpu_cortex_m4f_k22": values["cortex-m"],
     })
@@ -67,6 +70,7 @@
         "@//tools:cpu_roborio": values["32"],
         "@//tools:cpu_armhf": values["32"],
         "@//tools:cpu_cortex_m4f": values["32"],
+        "@//tools:cpu_cortex_m0plus": values["32"],
         # TODO(phil): Support this properly.
         #"@//tools:cpu_cortex_m4f_k22": values["32"],
     })
diff --git a/tools/ci/buildkite.yaml b/tools/ci/buildkite.yaml
index 9ccb606..8532a75 100644
--- a/tools/ci/buildkite.yaml
+++ b/tools/ci/buildkite.yaml
@@ -3,6 +3,7 @@
   COMMON: -c opt --stamp=no --curses=yes --symlink_prefix=/ --disk_cache=~/.cache/bazel/disk_cache/ --repo_env=FRC971_RUNNING_IN_CI=1
   TARGETS: //... @com_github_google_glog//... @com_google_ceres_solver//... @com_github_rawrtc_rawrtc//... @com_google_googletest//...
   M4F_TARGETS: //...
+  RP2040_TARGETS: //...
   # Sanity check that we are able to build the y2020 roborio code, which confirms
   # that we have the platform compatibility for the roborio set up correctly.
   ROBORIO_TARGETS: ${TARGETS} //y2020:download_stripped
@@ -32,3 +33,8 @@
     commands:
       - tools/ci/clean-disk.sh
       - tools/bazel ${STARTUP} --output_base=../cortex-m4f_output_base build ${COMMON} --config=cortex-m4f ${M4F_TARGETS}
+
+  - label: "rp2040"
+    commands:
+      - tools/ci/clean-disk.sh
+      - tools/bazel ${STARTUP} --output_base=../rp2040_output_base build ${COMMON} --config=rp2040 ${RP2040_TARGETS}
diff --git a/tools/cpp/BUILD b/tools/cpp/BUILD
index ea25dd1..0fe1512 100644
--- a/tools/cpp/BUILD
+++ b/tools/cpp/BUILD
@@ -9,6 +9,7 @@
         "armhf-debian": ":cc-compiler-armhf-debian",
         "roborio": ":cc-compiler-roborio",
         "cortex-m4f": ":cc-compiler-cortex-m4f",
+        "rp2040": ":cc-compiler-rp2040",
     },
     visibility = ["//visibility:public"],
 )
@@ -23,6 +24,7 @@
         "armhf-debian",
         "cortex-m4f",
         "cortex-m4f-k22",
+        "rp2040",
         "k8",
         "roborio",
     ]
@@ -40,6 +42,7 @@
         "//tools:has_asan": [],
         "//tools:has_tsan": [],
         "//tools:cpu_cortex_m4f": [],
+        "//tools:cpu_cortex_m0plus": [],
         # TODO(phil): Support this properly.
         #"//tools:cpu_cortex_m4f_k22": [],
         "//conditions:default": ["//third_party/gperftools:tcmalloc"],
@@ -342,6 +345,34 @@
 )
 
 cc_toolchain(
+    name = "cc-compiler-rp2040",
+    all_files = ":gcc_arm_none_eabi_none_files",
+    ar_files = ":gcc_arm_none_eabi_ar_files",
+    compiler_files = ":gcc_arm_none_eabi_compiler_files",
+    dwp_files = ":empty",
+    linker_files = ":gcc_arm_none_eabi_linker_files",
+    objcopy_files = "//tools/cpp/gcc_arm_none_eabi:objcopy",
+    strip_files = "//tools/cpp/gcc_arm_none_eabi:strip",
+    supports_param_files = 1,
+    toolchain_config = ":rp2040_toolchain_config",
+    toolchain_identifier = "rp2040",
+)
+
+toolchain(
+    name = "cc-toolchain-rp2040",
+    exec_compatible_with = [
+        "@platforms//os:linux",
+        "@platforms//cpu:x86_64",
+    ],
+    target_compatible_with = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m0plus",
+    ],
+    toolchain = ":cc-compiler-rp2040",
+    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
+
+cc_toolchain(
     name = "cc-compiler-cortex-m4f",
     all_files = ":gcc_arm_none_eabi_none_files",
     ar_files = ":gcc_arm_none_eabi_ar_files",
diff --git a/tools/cpp/toolchain_config.bzl b/tools/cpp/toolchain_config.bzl
index 7b0ffbf..6a306b6 100644
--- a/tools/cpp/toolchain_config.bzl
+++ b/tools/cpp/toolchain_config.bzl
@@ -13,6 +13,8 @@
 def _impl(ctx):
     if (ctx.attr.cpu == "armhf-debian"):
         toolchain_identifier = "clang_linux_armhf"
+    elif (ctx.attr.cpu == "rp2040"):
+        toolchain_identifier = "rp2040"
     elif (ctx.attr.cpu == "cortex-m4f"):
         toolchain_identifier = "cortex-m4f"
     elif (ctx.attr.cpu == "cortex-m4f-k22"):
@@ -30,7 +32,8 @@
         host_system_name = "armeabi-v7a"
     elif (ctx.attr.cpu == "armhf-debian"):
         host_system_name = "linux"
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22" or
           ctx.attr.cpu == "k8"):
         host_system_name = "local"
@@ -43,6 +46,8 @@
         target_system_name = "arm_a15"
     elif (ctx.attr.cpu == "armeabi-v7a"):
         target_system_name = "armeabi-v7a"
+    elif (ctx.attr.cpu == "rp2040"):
+        target_system_name = "rp2040"
     elif (ctx.attr.cpu == "cortex-m4f"):
         target_system_name = "cortex-m4f"
     elif (ctx.attr.cpu == "cortex-m4f-k22"):
@@ -58,6 +63,8 @@
         target_cpu = "armeabi-v7a"
     elif (ctx.attr.cpu == "armhf-debian"):
         target_cpu = "armhf-debian"
+    elif (ctx.attr.cpu == "rp2040"):
+        target_cpu = "rp2040"
     elif (ctx.attr.cpu == "cortex-m4f"):
         target_cpu = "cortex-m4f"
     elif (ctx.attr.cpu == "cortex-m4f-k22"):
@@ -71,6 +78,8 @@
 
     if (ctx.attr.cpu == "armeabi-v7a"):
         target_libc = "armeabi-v7a"
+    elif (ctx.attr.cpu == "rp2040"):
+        target_libc = "rp2040"
     elif (ctx.attr.cpu == "cortex-m4f"):
         target_libc = "cortex-m4f"
     elif (ctx.attr.cpu == "cortex-m4f-k22"):
@@ -89,7 +98,8 @@
         compiler = "clang"
     elif (ctx.attr.cpu == "armeabi-v7a"):
         compiler = "compiler"
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22" or
           ctx.attr.cpu == "roborio"):
         compiler = "gcc"
@@ -100,6 +110,8 @@
         abi_version = "armeabi-v7a"
     elif (ctx.attr.cpu == "armhf-debian"):
         abi_version = "clang_6.0"
+    elif (ctx.attr.cpu == "rp2040"):
+        abi_version = "rp2040"
     elif (ctx.attr.cpu == "cortex-m4f"):
         abi_version = "cortex-m4f"
     elif (ctx.attr.cpu == "cortex-m4f-k22"):
@@ -113,6 +125,8 @@
 
     if (ctx.attr.cpu == "armeabi-v7a"):
         abi_libc_version = "armeabi-v7a"
+    elif (ctx.attr.cpu == "rp2040"):
+        abi_libc_version = "rp2040"
     elif (ctx.attr.cpu == "cortex-m4f"):
         abi_libc_version = "cortex-m4f"
     elif (ctx.attr.cpu == "cortex-m4f-k22"):
@@ -202,7 +216,8 @@
             enabled = True,
             tools = [tool(path = "clang_6p0/x86_64-linux-gnu-objcopy")],
         )
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         objcopy_embed_data_action = action_config(
             action_name = "objcopy_embed_data",
@@ -215,6 +230,7 @@
     if (ctx.attr.cpu == "armeabi-v7a"):
         action_configs = []
     elif (ctx.attr.cpu == "armhf-debian" or
+          ctx.attr.cpu == "rp2040" or
           ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22" or
           ctx.attr.cpu == "k8" or
@@ -509,6 +525,88 @@
                 ),
             ],
         )
+    elif (ctx.attr.cpu == "rp2040"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.linkstamp_compile,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.lto_backend,
+                        ACTION_NAMES.clif_match,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-DPICO_BOARD=\"pico\"",
+                                "-DPICO_BUILD=1",
+                                "-DPICO_NO_HARDWARE=0",
+                                "-DPICO_ON_DEVICE=1",
+                                "-D__STDC_FORMAT_MACROS",
+                                "-D__STDC_CONSTANT_MACROS",
+                                "-D__STDC_LIMIT_MACROS",
+                                "-Wl,--gc-sections",
+                                "-fstack-protector",
+                                "-mcpu=cortex-m0plus",
+                                "-mthumb",
+                                "-fno-strict-aliasing",
+                                "-fmessage-length=80",
+                                "-fmax-errors=20",
+                                "-Wall",
+                                "-Wextra",
+                                "-Wpointer-arith",
+                                "-Wcast-qual",
+                                "-Wwrite-strings",
+                                "-Wtype-limits",
+                                "-Wsign-compare",
+                                "-Wformat=2",
+                                "-Werror",
+                                "-Wstrict-aliasing=2",
+                                "-Wno-misleading-indentation",
+                                "-Wno-int-in-bool-context",
+                                "-Wdouble-promotion",
+                                "-pipe",
+                                "-g",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.linkstamp_compile,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.lto_backend,
+                        ACTION_NAMES.clif_match,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-O3",
+                                "-finline-functions",
+                                "-funroll-loops",
+                                "-DNDEBUG",
+                                "-ffunction-sections",
+                            ],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+            ],
+        )
     elif (ctx.attr.cpu == "armhf-debian"):
         default_compile_flags_feature = feature(
             name = "default_compile_flags",
@@ -655,7 +753,8 @@
                 ),
             ],
         )
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         dbg_feature = feature(
             name = "dbg",
@@ -713,7 +812,8 @@
                 ),
             ],
         )
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         fastbuild_feature = feature(name = "fastbuild", implies = ["all_modes"])
     else:
@@ -788,7 +888,8 @@
             ],
             implies = ["all_modes"],
         )
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         opt_feature = feature(name = "opt", implies = ["all_modes"])
     else:
@@ -815,7 +916,8 @@
         ],
     )
 
-    if (ctx.attr.cpu == "cortex-m4f" or
+    if (ctx.attr.cpu == "rp2040" or
+        ctx.attr.cpu == "cortex-m4f" or
         ctx.attr.cpu == "cortex-m4f-k22"):
         include_paths_feature = feature(
             name = "include_paths",
@@ -993,6 +1095,30 @@
                 ),
             ],
         )
+    elif (ctx.attr.cpu == "rp2040"):
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-no-canonical-prefixes",
+                                "-mcpu=cortex-m0plus",
+                                "-mthumb",
+                                "-fno-strict-aliasing",
+                                "-Wl,--build-id=none",
+                                "--specs=nosys.specs",
+                                "-nostartfiles",
+                            ],
+                        ),
+                    ],
+                ),
+                # TODO(austin): I'd love to turn --gc-sections on, but that breaks things.
+            ],
+        )
     elif (ctx.attr.cpu == "k8"):
         default_link_flags_feature = feature(
             name = "default_link_flags",
@@ -1119,7 +1245,8 @@
                 ),
             ],
         )
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         all_modes_feature = feature(
             name = "all_modes",
@@ -1130,7 +1257,7 @@
                         ACTION_NAMES.assemble,
                         ACTION_NAMES.c_compile,
                     ],
-                    flag_groups = [flag_group(flags = ["--std=gnu99"])],
+                    flag_groups = [flag_group(flags = ["--std=gnu11"])],
                 ),
                 flag_set(
                     actions = [
@@ -1246,7 +1373,8 @@
                 ),
             ],
         )
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22" or
           ctx.attr.cpu == "roborio"):
         unfiltered_compile_flags_feature = feature(
@@ -1521,7 +1649,8 @@
         ],
     )
 
-    if (ctx.attr.cpu == "cortex-m4f" or
+    if (ctx.attr.cpu == "rp2040" or
+        ctx.attr.cpu == "cortex-m4f" or
         ctx.attr.cpu == "cortex-m4f-k22"):
         features = [
             default_compile_flags_feature,
@@ -1604,7 +1733,8 @@
             "%package(@linaro_linux_gcc_repo//lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%",
             "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/include)%/c++/7.4.1",
         ]
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         cxx_builtin_include_directories = [
             "/usr/lib/gcc/arm-none-eabi/4.8/include",
@@ -1714,7 +1844,8 @@
                 path = "clang_6p0/x86_64-linux-gnu-strip",
             ),
         ]
-    elif (ctx.attr.cpu == "cortex-m4f" or
+    elif (ctx.attr.cpu == "rp2040" or
+          ctx.attr.cpu == "cortex-m4f" or
           ctx.attr.cpu == "cortex-m4f-k22"):
         tool_paths = [
             tool_path(
@@ -1856,7 +1987,7 @@
 cc_toolchain_config = rule(
     implementation = _impl,
     attrs = {
-        "cpu": attr.string(mandatory = True, values = ["armeabi-v7a", "armhf-debian", "cortex-m4f", "cortex-m4f-k22", "k8", "roborio"]),
+        "cpu": attr.string(mandatory = True, values = ["armeabi-v7a", "armhf-debian", "cortex-m4f", "cortex-m4f-k22", "k8", "roborio", "rp2040"]),
     },
     provides = [CcToolchainConfigInfo],
     executable = True,
diff --git a/tools/platforms/BUILD b/tools/platforms/BUILD
index 4aa3db3..4df177c 100644
--- a/tools/platforms/BUILD
+++ b/tools/platforms/BUILD
@@ -47,4 +47,13 @@
     ],
 )
 
+platform(
+    name = "rp2040",
+    constraint_values = [
+        "@platforms//os:none",
+        "//tools/platforms/hardware:cortex_m0plus",
+        "//tools/platforms/go:lacks_support",
+    ],
+)
+
 # TODO(phil): Create something for "cortex-m4f-k22" builds.
diff --git a/tools/platforms/hardware/BUILD b/tools/platforms/hardware/BUILD
index 521b243..b33606a 100644
--- a/tools/platforms/hardware/BUILD
+++ b/tools/platforms/hardware/BUILD
@@ -19,3 +19,8 @@
     name = "cortex_m4f",
     constraint_setting = ":hardware",
 )
+
+constraint_value(
+    name = "cortex_m0plus",
+    constraint_setting = ":hardware",
+)
diff --git a/y2020/vision/sift/fast_gaussian.bzl b/y2020/vision/sift/fast_gaussian.bzl
index 5eaa4bf..b699282 100644
--- a/y2020/vision/sift/fast_gaussian.bzl
+++ b/y2020/vision/sift/fast_gaussian.bzl
@@ -39,6 +39,7 @@
             "roborio": "roborio",
             "armhf": "armhf-debian",
             "cortex-m": "cortex-m",
+            "cortex-m0plus": "cortex-m0plus",
         }),
         outs = headers + objects + htmls,
         # The tool doesn't support anything other than k8 and armhf-debian