[stm32] Add pw_board_led_stm32cubef4

The Port/Pin overrides are needed because the F429 Discover and the F439
Nucleo use different pins for the onboard LED's.

Change-Id: Ie5e006a99978d9021de525abdc1410ba77a4f48c
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/experimental/+/39767
Commit-Queue: Varun Sharma <vars@google.com>
Reviewed-by: Yecheng Zhao <zyecheng@google.com>
Reviewed-by: Ali Zhang <alizhang@google.com>
diff --git a/build_overrides/pigweed.gni b/build_overrides/pigweed.gni
index aa24630..d40f911 100644
--- a/build_overrides/pigweed.gni
+++ b/build_overrides/pigweed.gni
@@ -27,6 +27,8 @@
   dir_pw_board_led_host = get_path_info("//pw_board_led_host", "abspath")
   dir_pw_board_led_stm32f429i_disc1 =
       get_path_info("//pw_board_led_stm32f429i_disc1", "abspath")
+  dir_pw_board_led_stm32cubef4 =
+      get_path_info("//pw_board_led_stm32cubef4", "abspath")
   dir_pw_console = get_path_info("//pw_console", "abspath")
   dir_pw_spin_delay = get_path_info("//pw_spin_delay", "abspath")
   dir_pw_spin_delay_arduino =
diff --git a/pw_board_led_stm32cubef4/BUILD.gn b/pw_board_led_stm32cubef4/BUILD.gn
new file mode 100644
index 0000000..843f13d
--- /dev/null
+++ b/pw_board_led_stm32cubef4/BUILD.gn
@@ -0,0 +1,44 @@
+# 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")
+
+declare_args() {
+  # GPIO Port of LED (ex. "G")
+  pw_board_led_stm32cubef4_gpio_port = ""
+
+  # GPIO Pin of LED (ex. "13")
+  pw_board_led_stm32cubef4_gpio_pin = ""
+}
+
+config("flags") {
+  cflags = [
+    "-DLED_PORT_CHAR=" + pw_board_led_stm32cubef4_gpio_port,
+    "-DLED_PIN_NUM=" + pw_board_led_stm32cubef4_gpio_pin,
+  ]
+}
+
+if (pw_board_led_stm32cubef4_gpio_port != "" &&
+    pw_board_led_stm32cubef4_gpio_pin != "") {
+  pw_source_set("pw_board_led_stm32cubef4") {
+    public_configs = [ ":flags" ]
+    deps = [
+      "$dir_pw_board_led:pw_board_led.facade",
+      "//third_party/stm32cubef4:stm32f4xx_hal",
+    ]
+    sources = [ "led.cc" ]
+  }
+}
diff --git a/pw_board_led_stm32cubef4/led.cc b/pw_board_led_stm32cubef4/led.cc
new file mode 100644
index 0000000..adee2b5
--- /dev/null
+++ b/pw_board_led_stm32cubef4/led.cc
@@ -0,0 +1,53 @@
+// 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.
+
+#include "pw_board_led/led.h"
+
+#include <cinttypes>
+
+#include "stm32f4xx.h"
+
+namespace pw::board_led {
+
+#define _CAT(A, B, C) A##B##C
+#define CAT(A, B, C) _CAT(A, B, C)
+
+#define LED_PORT CAT(GPIO, LED_PORT_CHAR, )
+#define LED_PIN CAT(GPIO_PIN_, LED_PIN_NUM, )
+
+// This is hacky, but works. It is needed because there is no function to
+// initialize an arbitrary GPIO port.
+#define LED_PORT_ENABLE CAT(__HAL_RCC_GPIO, LED_PORT_CHAR, _CLK_ENABLE)
+
+void Init() {
+  GPIO_InitTypeDef GPIO_InitStruct = {};
+
+  LED_PORT_ENABLE();
+
+  HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
+
+  GPIO_InitStruct.Pin = LED_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+  HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
+}
+
+void TurnOff() { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); }
+
+void TurnOn() { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); }
+
+void Toggle() { HAL_GPIO_TogglePin(LED_PORT, LED_PIN); }
+
+}  // namespace pw::board_led