FPGA config application
- New app added for fpga configuration. No functionality present yet.
- New pin_config library for common board pin config tasks.
Bug: b/310961133
Change-Id: Ice4e224ea7cc889caacaf636ee73304925337b66
Reviewed-on: https://pigweed-review.googlesource.com/c/gonk/+/181296
Reviewed-by: Eric Holland <hollande@google.com>
Commit-Queue: Anthony DiGirolamo <tonymd@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 53fc8c2..2120617 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -35,6 +35,7 @@
"//applications/system_example(//targets/stm32f769i_disc0_stm32cube:stm32f769i_disc0_stm32cube.size_optimized)",
# Arduino targets
+ "//applications/fpga_config($dir_pigweed/targets/arduino:arduino_size_optimized)",
"//applications/spi_flash_test($dir_pigweed/targets/arduino:arduino_size_optimized)",
]
}
diff --git a/applications/fpga_config/BUILD.gn b/applications/fpga_config/BUILD.gn
new file mode 100644
index 0000000..7bc6b85
--- /dev/null
+++ b/applications/fpga_config/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright 2023 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_arduino_build/arduino.gni")
+import("$dir_pw_build/target_types.gni")
+
+pw_executable("fpga_config") {
+ include_dirs = [ "//third_party/stm32duino/arduino-core/libraries/SPI/src" ]
+
+ sources = [
+ "//third_party/stm32duino/arduino-core/libraries/SPI/src/SPI.cpp",
+ "//third_party/stm32duino/arduino-core/libraries/SPI/src/utility/spi_com.c",
+ "main.cc",
+ ]
+
+ deps = [
+ "$dir_pw_log",
+ "$dir_pw_string",
+ "$dir_pw_third_party/arduino:arduino_core_sources",
+ "//lib/pin_config",
+ ]
+
+ ldflags = [ "-Wl,--print-memory-usage" ]
+
+ remove_configs = [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ]
+}
diff --git a/applications/fpga_config/main.cc b/applications/fpga_config/main.cc
new file mode 100644
index 0000000..89adae2
--- /dev/null
+++ b/applications/fpga_config/main.cc
@@ -0,0 +1,57 @@
+// Copyright 2023 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 <cstdint>
+
+#include <Arduino.h>
+#include <SPI.h>
+
+#include "pw_log/log.h"
+
+#include "gonk/pin_config.h"
+
+using gonk::pin_config::PinConfig;
+using gonk::pin_config::StatusLed;
+
+namespace {
+
+PinConfig pin_config = PinConfig();
+
+} // namespace
+
+int main() {
+ pin_config.Init();
+ pin_config.InitFpgaPins();
+ pin_config.FpgaHalt();
+ pin_config.FpgaEnable();
+ delay(10);
+
+ uint16_t update_count = 0;
+
+ while (true) {
+ PW_LOG_INFO("update: %u", update_count);
+ delay(1000);
+
+ update_count = (update_count + 1) % UINT16_MAX;
+
+ // Toggle status LED each loop.
+ if (update_count % 2 == 0) {
+ digitalWrite(StatusLed, HIGH);
+ } else {
+ digitalWrite(StatusLed, LOW);
+ }
+ }
+
+ return 0;
+}
diff --git a/applications/spi_flash_test/BUILD.gn b/applications/spi_flash_test/BUILD.gn
index 69cb2f4..dd3cd63 100644
--- a/applications/spi_flash_test/BUILD.gn
+++ b/applications/spi_flash_test/BUILD.gn
@@ -30,6 +30,7 @@
"$dir_pw_log",
"$dir_pw_string",
"$dir_pw_third_party/arduino:arduino_core_sources",
+ "//lib/pin_config",
]
ldflags = [ "-Wl,--print-memory-usage" ]
diff --git a/applications/spi_flash_test/main.cc b/applications/spi_flash_test/main.cc
index e1d9bef..514817c 100644
--- a/applications/spi_flash_test/main.cc
+++ b/applications/spi_flash_test/main.cc
@@ -12,46 +12,35 @@
// License for the specific language governing permissions and limitations under
// the License.
-#include <Arduino.h>
#include <cstdint>
+#include <Arduino.h>
#include <SPI.h>
#include "pw_log/log.h"
#include "pw_string/format.h"
-// STM32 Port & pin // PCB NET Name
-const int ICE40Reset = PC13; // ICE_RST_N
-const int ICE40Done = PC8; // ICE_CDONE
-const int FlashCS = PD2; // ICE_SPI_SS
-const int FlashHold = PC11; // FLASH_HOLD
-const int FlashWP = PC12; // FLASH_WP
-const int FlashMOSI = PB5; // ICE_SPI_MOSI
-const int FlashMISO = PB4; // ICE_SPI_MOSI
-const int FlashCLK = PB3; // ICE_SPI_SCK
-const int StatusLed = PB13; // STATUS
+#include "gonk/pin_config.h"
+
+using gonk::pin_config::FlashCS;
+using gonk::pin_config::PinConfig;
+using gonk::pin_config::StatusLed;
+
+namespace {
+
+PinConfig pin_config = PinConfig();
+
+} // namespace
int main() {
- Serial.begin(115200);
+ pin_config.Init();
// Put FPGA in reset.
- PW_LOG_INFO("Hold FPGA in reset");
- pinMode(ICE40Reset, OUTPUT);
- digitalWrite(ICE40Reset, LOW);
+ pin_config.InitFpgaPins();
+ pin_config.FpgaHalt();
delay(10);
- // Debug status LED
- pinMode(StatusLed, OUTPUT);
- digitalWrite(StatusLed, LOW);
-
- // SPI pin definitions
- pinMode(FlashCS, OUTPUT);
- digitalWrite(FlashCS, HIGH);
-
- SPI.setMISO(FlashMISO);
- SPI.setMOSI(FlashMOSI);
- SPI.setSCLK(FlashCLK);
- SPI.begin();
+ pin_config.SPIEnable();
char buffer[32];
uint16_t update_count = 0;
diff --git a/lib/pin_config/BUILD.gn b/lib/pin_config/BUILD.gn
new file mode 100644
index 0000000..ef9b399
--- /dev/null
+++ b/lib/pin_config/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2023 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")
+
+config("default_config") {
+ include_dirs = [ "public" ]
+}
+
+pw_source_set("pin_config") {
+ public_configs = [ ":default_config" ]
+ public = [ "public/gonk/pin_config.h" ]
+
+ include_dirs = [ "//third_party/stm32duino/arduino-core/libraries/SPI/src" ]
+
+ sources = [ "pin_config.cc" ]
+
+ deps = [
+ "$dir_pw_log",
+ "$dir_pw_third_party/arduino:arduino_core_sources",
+ ]
+}
diff --git a/lib/pin_config/pin_config.cc b/lib/pin_config/pin_config.cc
new file mode 100644
index 0000000..61719e0
--- /dev/null
+++ b/lib/pin_config/pin_config.cc
@@ -0,0 +1,65 @@
+#include <Arduino.h>
+#include <SPI.h>
+
+#include "gonk/pin_config.h"
+
+#define PW_LOG_LEVEL PW_LOG_LEVEL_DEBUG
+#define PW_LOG_MODULE_NAME "PinConfig"
+
+#include "pw_log/log.h"
+
+namespace gonk::pin_config {
+
+PinConfig::PinConfig() {}
+
+void PinConfig::Init() {
+ // Set STATUS LED mode and initial state.
+ pinMode(StatusLed, OUTPUT);
+ digitalWrite(StatusLed, LOW);
+
+ // Default CS pin to output high.
+ pinMode(FlashCS, OUTPUT);
+ digitalWrite(FlashCS, HIGH);
+}
+
+void PinConfig::InitFpgaPins() {
+ // Set FPGA reset pin mode and initial state.
+ pinMode(ICE40ResetN, OUTPUT);
+ digitalWrite(ICE40ResetN, HIGH);
+
+ // Set FPGA configure done signal pin as an input.
+ pinMode(ICE40Done, INPUT);
+}
+
+void PinConfig::FpgaHalt() {
+ // Set FlashCS to signal the FPGA it should load the bitstream from external
+ // flash.
+ pinMode(FlashCS, INPUT_FLOATING);
+
+ // Hold in reset for a small amount of time.
+ digitalWrite(ICE40ResetN, LOW);
+ delay(50);
+
+ // Boot fpga and give it time to reset any internal SPI pin configuration.
+ digitalWrite(ICE40ResetN, HIGH);
+ delay(10);
+
+ // Finally, hold in reset.
+ digitalWrite(ICE40ResetN, LOW);
+}
+
+void PinConfig::FpgaEnable() { digitalWrite(ICE40ResetN, HIGH); }
+
+void PinConfig::SPIEnable() {
+ // SPI pin definitions
+ SPI.setMISO(FlashMISO);
+ SPI.setMOSI(FlashMOSI);
+ SPI.setSCLK(FlashCLK);
+ SPI.begin();
+
+ // Set FlashCS as output with initial state.
+ pinMode(FlashCS, OUTPUT);
+ digitalWrite(FlashCS, HIGH);
+}
+
+} // namespace gonk::pin_config
diff --git a/lib/pin_config/public/gonk/pin_config.h b/lib/pin_config/public/gonk/pin_config.h
new file mode 100644
index 0000000..3f6d72a
--- /dev/null
+++ b/lib/pin_config/public/gonk/pin_config.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <Arduino.h>
+
+namespace gonk::pin_config {
+
+// STM32 Port & pin // PCB NET Name
+constexpr uint16_t ICE40ResetN = PC13; // ICE_RST_N
+constexpr uint16_t ICE40Done = PC8; // ICE_CDONE
+constexpr uint16_t FlashCS = PD2; // ICE_SPI_SS
+constexpr uint16_t FlashHold = PC11; // FLASH_HOLD
+constexpr uint16_t FlashWP = PC12; // FLASH_WP
+constexpr uint16_t FlashMOSI = PB5; // ICE_SPI_MOSI
+constexpr uint16_t FlashMISO = PB4; // ICE_SPI_MISO
+constexpr uint16_t FlashCLK = PB3; // ICE_SPI_SCK
+constexpr uint16_t StatusLed = PB13; // STATUS
+
+class PinConfig {
+public:
+ PinConfig();
+
+ // Init common MCU pins such as the status LED.
+ void Init();
+ // Init FPGA specific pins.
+ void InitFpgaPins();
+
+ // Halt the FPGA with the SPI bus released so SPI flash is accessible from the
+ // MCU.
+ void FpgaHalt();
+ void FpgaEnable();
+ void SPIEnable();
+
+private:
+};
+
+} // namespace gonk::pin_config