pw_sync_baremetal: Add scaffolding for baremetal

Adds a dummy spin lock backend implementation for baremetal
configuration.

The provided implementation makes a single attempt to acquire the
lock and asserts if it is unavailable. It does not perform interrupt
masking or disable global interrupts, so this implementation does
not support simultaneous multi-threaded environments including IRQs,
and is only meant to prevent data corruption.

Change-Id: I4d44b2dd5cc6f38be1188a9f480f61c6d042b855
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/30520
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Prashanth Swaminathan <prashanthsw@google.com>
diff --git a/docs/BUILD.gn b/docs/BUILD.gn
index 012fe80..7c2f2bf 100644
--- a/docs/BUILD.gn
+++ b/docs/BUILD.gn
@@ -99,6 +99,7 @@
     "$dir_pw_stream:docs",
     "$dir_pw_string:docs",
     "$dir_pw_sync:docs",
+    "$dir_pw_sync_baremetal:docs",
     "$dir_pw_sync_stl:docs",
     "$dir_pw_sync_threadx:docs",
     "$dir_pw_sys_io:docs",
diff --git a/modules.gni b/modules.gni
index 1604d2e..49679be 100644
--- a/modules.gni
+++ b/modules.gni
@@ -77,6 +77,7 @@
   dir_pw_string = get_path_info("pw_string", "abspath")
   dir_pw_sync = get_path_info("pw_sync", "abspath")
   dir_pw_sync_freertos = get_path_info("pw_sync_freertos", "abspath")
+  dir_pw_sync_baremetal = get_path_info("pw_sync_baremetal", "abspath")
   dir_pw_sync_stl = get_path_info("pw_sync_stl", "abspath")
   dir_pw_sync_threadx = get_path_info("pw_sync_threadx", "abspath")
   dir_pw_sys_io = get_path_info("pw_sys_io", "abspath")
diff --git a/pw_sync_baremetal/BUILD b/pw_sync_baremetal/BUILD
new file mode 100644
index 0000000..aa7c5c4
--- /dev/null
+++ b/pw_sync_baremetal/BUILD
@@ -0,0 +1,46 @@
+# Copyright 2021 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.
+
+load(
+    "//pw_build:pigweed.bzl",
+    "pw_cc_library",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])  # Apache License 2.0
+
+pw_cc_library(
+    name = "spin_lock_headers",
+    hdrs = [
+        "public/pw_sync_baremetal/spin_lock_inline.h",
+        "public/pw_sync_baremetal/spin_lock_native.h",
+        "public_overrides/pw_sync_backend/spin_lock_inline.h",
+        "public_overrides/pw_sync_backend/spin_lock_native.h",
+    ],
+    includes = [
+        "public",
+        "public_overrides",
+    ],
+)
+
+pw_cc_library(
+    name = "spin_lock",
+    deps = [
+        ":spin_lock_headers",
+        "//pw_assert",
+        "//pw_sync:spin_lock_facade",
+        "//pw_sync:yield_core",
+    ],
+)
diff --git a/pw_sync_baremetal/BUILD.gn b/pw_sync_baremetal/BUILD.gn
new file mode 100644
index 0000000..fd4fff5
--- /dev/null
+++ b/pw_sync_baremetal/BUILD.gn
@@ -0,0 +1,56 @@
+# Copyright 2021 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.
+
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/target_types.gni")
+import("$dir_pw_chrono/backend.gni")
+import("$dir_pw_docgen/docs.gni")
+
+config("public_include_path") {
+  include_dirs = [ "public" ]
+  visibility = [ ":*" ]
+}
+
+config("backend_config") {
+  include_dirs = [ "public_overrides" ]
+  visibility = [ ":*" ]
+}
+
+# This target provides the backend for pw::sync::SpinLock.
+# The provided implementation makes a single attempt to acquire the lock and asserts
+# if it is unavailable. It does not perform interrupt masking or disable global
+# interrupts, so this implementation does not support simultaneous multi-threaded
+# environments including IRQs, and is only meant to prevent data corruption.
+pw_source_set("spin_lock_backend") {
+  public_configs = [
+    ":public_include_path",
+    ":backend_config",
+  ]
+  public = [
+    "public/pw_sync_baremetal/spin_lock_inline.h",
+    "public/pw_sync_baremetal/spin_lock_native.h",
+    "public_overrides/pw_sync_backend/spin_lock_inline.h",
+    "public_overrides/pw_sync_backend/spin_lock_native.h",
+  ]
+  public_deps = [
+    "$dir_pw_assert",
+    "$dir_pw_sync:spin_lock.facade",
+    "$dir_pw_sync:yield_core",
+  ]
+}
+
+pw_doc_group("docs") {
+  sources = [ "docs.rst" ]
+}
diff --git a/pw_sync_baremetal/docs.rst b/pw_sync_baremetal/docs.rst
new file mode 100644
index 0000000..1fbd99e
--- /dev/null
+++ b/pw_sync_baremetal/docs.rst
@@ -0,0 +1,11 @@
+.. _module-pw_sync_baremetal:
+
+-----------------
+pw_sync_baremetal
+-----------------
+This is a set of backends for pw_sync that works on baremetal targets. It is not
+ready for use, and is under construction. The provided implementation makes a
+single attempt to acquire the lock and asserts if it is unavailable. It does not
+perform interrupt masking or disable global interrupts, so this implementation
+does not support simultaneous multi-threaded environments including IRQs, and is
+only meant to prevent data corruption.
diff --git a/pw_sync_baremetal/public/pw_sync_baremetal/spin_lock_inline.h b/pw_sync_baremetal/public/pw_sync_baremetal/spin_lock_inline.h
new file mode 100644
index 0000000..801d738
--- /dev/null
+++ b/pw_sync_baremetal/public/pw_sync_baremetal/spin_lock_inline.h
@@ -0,0 +1,39 @@
+// Copyright 2021 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.
+#pragma once
+
+#include "pw_assert/light.h"
+#include "pw_sync/spin_lock.h"
+#include "pw_sync/yield_core.h"
+
+namespace pw::sync {
+
+inline SpinLock::SpinLock() : native_type_() {}
+
+inline void SpinLock::lock() { PW_ASSERT(try_lock()); }
+
+inline bool SpinLock::try_lock() {
+  // TODO(pwbug/303): Use the pw_interrupt API here to disable interrupts.
+  return !native_type_.test_and_set(std::memory_order_acquire);
+}
+
+inline void SpinLock::unlock() {
+  native_type_.clear(std::memory_order_release);
+}
+
+inline SpinLock::native_handle_type SpinLock::native_handle() {
+  return native_type_;
+}
+
+}  // namespace pw::sync
diff --git a/pw_sync_baremetal/public/pw_sync_baremetal/spin_lock_native.h b/pw_sync_baremetal/public/pw_sync_baremetal/spin_lock_native.h
new file mode 100644
index 0000000..6bb6abd
--- /dev/null
+++ b/pw_sync_baremetal/public/pw_sync_baremetal/spin_lock_native.h
@@ -0,0 +1,23 @@
+// Copyright 2021 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.
+#pragma once
+
+#include <atomic>
+
+namespace pw::sync::backend {
+
+using NativeSpinLock = std::atomic_flag;
+using NativeSpinLockHandle = std::atomic_flag&;
+
+}  // namespace pw::sync::backend
diff --git a/pw_sync_baremetal/public_overrides/pw_sync_backend/spin_lock_inline.h b/pw_sync_baremetal/public_overrides/pw_sync_backend/spin_lock_inline.h
new file mode 100644
index 0000000..65a64b0
--- /dev/null
+++ b/pw_sync_baremetal/public_overrides/pw_sync_backend/spin_lock_inline.h
@@ -0,0 +1,16 @@
+// Copyright 2021 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.
+#pragma once
+
+#include "pw_sync_baremetal/spin_lock_inline.h"
diff --git a/pw_sync_baremetal/public_overrides/pw_sync_backend/spin_lock_native.h b/pw_sync_baremetal/public_overrides/pw_sync_backend/spin_lock_native.h
new file mode 100644
index 0000000..ed8ad48
--- /dev/null
+++ b/pw_sync_baremetal/public_overrides/pw_sync_backend/spin_lock_native.h
@@ -0,0 +1,16 @@
+// Copyright 2021 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.
+#pragma once
+
+#include "pw_sync_baremetal/spin_lock_native.h"
diff --git a/targets/stm32f429i-disc1/target_toolchains.gni b/targets/stm32f429i-disc1/target_toolchains.gni
index e6eae02..06f8d1c 100644
--- a/targets/stm32f429i-disc1/target_toolchains.gni
+++ b/targets/stm32f429i-disc1/target_toolchains.gni
@@ -48,6 +48,7 @@
   pw_cpu_exception_ENTRY_BACKEND = dir_pw_cpu_exception_armv7m
   pw_cpu_exception_HANDLER_BACKEND = "$dir_pw_cpu_exception:basic_handler"
   pw_cpu_exception_SUPPORT_BACKEND = "$dir_pw_cpu_exception_armv7m:support"
+  pw_sync_SPIN_LOCK_BACKEND = "$dir_pw_sync_baremetal:spin_lock_backend"
   pw_log_BACKEND = dir_pw_log_basic
   pw_sys_io_BACKEND = dir_pw_sys_io_baremetal_stm32f429
   pw_rpc_system_server_BACKEND =