pw_sys_io_stm32cube: Add module
Moves pw_sys_io_stm32cube from experimental to Pigweed core.
Requires: 73181
Change-Id: I36170562671153488f2b54f954aa0970aac09063
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/72961
Pigweed-Auto-Submit: Armando Montanez <amontanez@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/modules.gni b/modules.gni
index d2d8929..8ec4909 100644
--- a/modules.gni
+++ b/modules.gni
@@ -105,6 +105,7 @@
dir_pw_sys_io_arduino = get_path_info("pw_sys_io_arduino", "abspath")
dir_pw_sys_io_mcuxpresso = get_path_info("pw_sys_io_mcuxpresso", "abspath")
dir_pw_sys_io_stdio = get_path_info("pw_sys_io_stdio", "abspath")
+ dir_pw_sys_io_stm32cube = get_path_info("pw_sys_io_stm32cube", "abspath")
dir_pw_system = get_path_info("pw_system", "abspath")
dir_pw_target_runner = get_path_info("pw_target_runner", "abspath")
dir_pw_thread = get_path_info("pw_thread", "abspath")
diff --git a/pw_sys_io_stm32cube/BUILD.bazel b/pw_sys_io_stm32cube/BUILD.bazel
new file mode 100644
index 0000000..a88c64f
--- /dev/null
+++ b/pw_sys_io_stm32cube/BUILD.bazel
@@ -0,0 +1,34 @@
+# 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"])
+
+pw_cc_library(
+ name = "pw_sys_io_stm32cube",
+ srcs = ["sys_io.cc"],
+ hdrs = ["public/pw_sys_io_stm32cube/init.h"],
+ deps = [
+ "//pw_preprocessor",
+ "//pw_status",
+ "//pw_sys_io",
+ "//third_party/stm32cube",
+ ],
+)
diff --git a/pw_sys_io_stm32cube/BUILD.gn b/pw_sys_io_stm32cube/BUILD.gn
new file mode 100644
index 0000000..6b9c439
--- /dev/null
+++ b/pw_sys_io_stm32cube/BUILD.gn
@@ -0,0 +1,58 @@
+# 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_docgen/docs.gni")
+
+# Defaults to USART1 on the STM32F429xx, but can be overridden.
+declare_args() {
+ # USART to use for sys_io
+ pw_sys_io_stm32cube_usart_num = "1"
+
+ # GPIO Port of the specified USART
+ pw_sys_io_stm32cube_gpio_port = "A"
+
+ # GPIO Pin for tx
+ pw_sys_io_stm32cube_gpio_tx_pin = "9"
+
+ # GPIO Pin for rx
+ pw_sys_io_stm32cube_gpio_rx_pin = "10"
+}
+
+config("public_includes") {
+ include_dirs = [ "public" ]
+}
+
+pw_source_set("pw_sys_io_stm32cube") {
+ defines = [
+ "USART_NUM=$pw_sys_io_stm32cube_usart_num",
+ "USART_GPIO_PORT_CHAR=$pw_sys_io_stm32cube_gpio_port",
+ "USART_TX_PIN_NUM=$pw_sys_io_stm32cube_gpio_tx_pin",
+ "USART_RX_PIN_NUM=$pw_sys_io_stm32cube_gpio_rx_pin",
+ ]
+ public_configs = [ ":public_includes" ]
+ public_deps = [
+ "$dir_pw_preprocessor",
+ "$dir_pw_status",
+ "$dir_pw_third_party/stm32cube",
+ ]
+ public = [ "public/pw_sys_io_stm32cube/init.h" ]
+ sources = [ "sys_io.cc" ]
+ deps = [
+ "$dir_pw_sys_io:default_putget_bytes",
+ "$dir_pw_sys_io:facade",
+ ]
+}
diff --git a/pw_sys_io_stm32cube/public/pw_sys_io_stm32cube/init.h b/pw_sys_io_stm32cube/public/pw_sys_io_stm32cube/init.h
new file mode 100644
index 0000000..d2dd464
--- /dev/null
+++ b/pw_sys_io_stm32cube/public/pw_sys_io_stm32cube/init.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 "pw_preprocessor/util.h"
+
+PW_EXTERN_C_START
+
+// The actual implement of PreMainInit() in sys_io_BACKEND.
+void pw_sys_io_Init(void);
+
+PW_EXTERN_C_END
diff --git a/pw_sys_io_stm32cube/sys_io.cc b/pw_sys_io_stm32cube/sys_io.cc
new file mode 100644
index 0000000..ef8eebb
--- /dev/null
+++ b/pw_sys_io_stm32cube/sys_io.cc
@@ -0,0 +1,99 @@
+// 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_sys_io/sys_io.h"
+
+#include <cinttypes>
+
+#include "pw_status/status.h"
+#include "stm32cube/stm32cube.h"
+
+#define _CAT(A, B, C) A##B##C
+#define CAT(A, B, C) _CAT(A, B, C)
+
+#define USART_INSTANCE CAT(USART, USART_NUM, )
+#define USART_GPIO_ALTERNATE_FUNC CAT(GPIO_AF7_USART, USART_NUM, )
+#define USART_GPIO_PORT CAT(GPIO, USART_GPIO_PORT_CHAR, )
+#define USART_GPIO_TX_PIN CAT(GPIO_PIN_, USART_TX_PIN_NUM, )
+#define USART_GPIO_RX_PIN CAT(GPIO_PIN_, USART_RX_PIN_NUM, )
+
+#define USART_GPIO_PORT_ENABLE \
+ CAT(__HAL_RCC_GPIO, USART_GPIO_PORT_CHAR, _CLK_ENABLE)
+#define USART_ENABLE CAT(__HAL_RCC_USART, USART_NUM, _CLK_ENABLE)
+
+static UART_HandleTypeDef uart;
+
+extern "C" void pw_sys_io_Init() {
+ GPIO_InitTypeDef GPIO_InitStruct = {};
+
+ USART_ENABLE();
+ USART_GPIO_PORT_ENABLE();
+
+ GPIO_InitStruct.Pin = USART_GPIO_TX_PIN | USART_GPIO_RX_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = USART_GPIO_ALTERNATE_FUNC;
+ HAL_GPIO_Init(USART_GPIO_PORT, &GPIO_InitStruct);
+
+ uart.Instance = USART_INSTANCE;
+ uart.Init.BaudRate = 115200;
+ uart.Init.WordLength = UART_WORDLENGTH_8B;
+ uart.Init.StopBits = UART_STOPBITS_1;
+ uart.Init.Parity = UART_PARITY_NONE;
+ uart.Init.Mode = UART_MODE_TX_RX;
+ uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ uart.Init.OverSampling = UART_OVERSAMPLING_16;
+ HAL_UART_Init(&uart);
+}
+
+// This whole implementation is very inefficient because it uses the synchronous
+// polling UART API and only reads / writes 1 byte at a time.
+namespace pw::sys_io {
+Status ReadByte(std::byte* dest) {
+ if (HAL_UART_Receive(
+ &uart, reinterpret_cast<uint8_t*>(dest), 1, HAL_MAX_DELAY) !=
+ HAL_OK) {
+ return Status::ResourceExhausted();
+ }
+ return OkStatus();
+}
+
+Status TryReadByte(std::byte* dest) { return Status::Unimplemented(); }
+
+Status WriteByte(std::byte b) {
+ if (HAL_UART_Transmit(
+ &uart, reinterpret_cast<uint8_t*>(&b), 1, HAL_MAX_DELAY) != HAL_OK) {
+ return Status::ResourceExhausted();
+ }
+ return OkStatus();
+}
+
+// Writes a string using pw::sys_io, and add newline characters at the end.
+StatusWithSize WriteLine(const std::string_view& s) {
+ size_t chars_written = 0;
+ StatusWithSize result = WriteBytes(std::as_bytes(std::span(s)));
+ if (!result.ok()) {
+ return result;
+ }
+ chars_written += result.size();
+
+ // Write trailing newline.
+ result = WriteBytes(std::as_bytes(std::span("\r\n", 2)));
+ chars_written += result.size();
+
+ return StatusWithSize(OkStatus(), chars_written);
+}
+
+} // namespace pw::sys_io