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