libtrellis: Allow specifying spimode for ecppack During read from SPI Flash, once this command is reached, the device will switch to specified mode. Available modes: * Read (default) * Fast Read * Dual SPI Read * Quad SPI Read Signed-off-by: Jens Andersen <jens.andersen@gmail.com>
diff --git a/libtrellis/include/Bitstream.hpp b/libtrellis/include/Bitstream.hpp index 7e00910..08b2d82 100644 --- a/libtrellis/include/Bitstream.hpp +++ b/libtrellis/include/Bitstream.hpp
@@ -12,6 +12,7 @@ namespace Trellis { enum class BitstreamCommand : uint8_t { + SPI_MODE = 0b01111001, LSC_RESET_CRC = 0b00111011, VERIFY_ID = 0b11100010, LSC_WRITE_COMP_DIC = 0b00000010,
diff --git a/libtrellis/src/Bitstream.cpp b/libtrellis/src/Bitstream.cpp index 16d6c8c..d87186a 100644 --- a/libtrellis/src/Bitstream.cpp +++ b/libtrellis/src/Bitstream.cpp
@@ -23,6 +23,11 @@ {"38.8", 0x38}, {"62.0", 0x3b}}; +static const vector<pair<std::string, uint8_t>> spi_modes = + {{"fast-read", 0x49}, + {"dual-spi", 0x51}, + {"qspi", 0x59}}; + // The BitstreamReadWriter class stores state (including CRC16) whilst reading // the bitstream class BitstreamReadWriter { @@ -356,6 +361,20 @@ rd.check_crc16(); } break; + case BitstreamCommand::SPI_MODE: { + uint8_t spi_mode; + rd.get_bytes(&spi_mode, 1); + rd.skip_bytes(2); + + auto spimode = find_if(spi_modes.begin(), spi_modes.end(), [&](const pair<string, uint8_t> &fp){ + return fp.second == spi_mode; + }); + if (spimode == spi_modes.end()) + throw runtime_error("bad SPI mode" + std::to_string(spi_mode)); + + BITSTREAM_NOTE("SPI Mode " << spimode->first); + } + break; case BitstreamCommand::DUMMY: break; default: BITSTREAM_FATAL("unsupported command 0x" << hex << setw(2) << setfill('0') << int(cmd), @@ -375,6 +394,19 @@ wr.write_bytes(preamble.begin(), preamble.size()); // Padding wr.insert_dummy(4); + + if (options.count("spimode")) { + auto spimode = find_if(spi_modes.begin(), spi_modes.end(), [&](const pair<string, uint8_t> &fp){ + return fp.first == options.at("spimode"); + }); + if (spimode == spi_modes.end()) + throw runtime_error("bad spimode option " + options.at("spimode")); + + wr.write_byte(uint8_t(BitstreamCommand::SPI_MODE)); + wr.write_byte(uint8_t(spimode->second)); + wr.insert_zeros(2); + } + // Reset CRC wr.write_byte(uint8_t(BitstreamCommand::LSC_RESET_CRC)); wr.insert_zeros(3);
diff --git a/libtrellis/tools/ecppack.cpp b/libtrellis/tools/ecppack.cpp index 5ae362e..31a3f2b 100644 --- a/libtrellis/tools/ecppack.cpp +++ b/libtrellis/tools/ecppack.cpp
@@ -35,6 +35,7 @@ options.add_options()("freq", po::value<std::string>(), "config frequency in MHz"); options.add_options()("svf", po::value<std::string>(), "output SVF file"); options.add_options()("svf-rowsize", po::value<int>(), "SVF row size in bits (default 8000)"); + options.add_options()("spimode", po::value<std::string>(), "SPI Mode to use (fast-read, dual-spi, qspi)"); po::positional_options_description pos; options.add_options()("input", po::value<std::string>()->required(), "input textual configuration"); @@ -110,6 +111,9 @@ if (vm.count("freq")) bitopts["freq"] = vm["freq"].as<string>(); + if (vm.count("spimode")) + bitopts["spimode"] = vm["spimode"].as<string>(); + Bitstream b = Bitstream::serialise_chip(c, bitopts); if (vm.count("bit")) { ofstream bit_file(vm["bit"].as<string>(), ios::binary);