diff --git a/CMakeLists.txt b/CMakeLists.txt index 94f8fd0..8320494 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,8 @@ set(OPENFPGALOADER_SOURCE src/anlogicBitParser.cpp src/anlogicCable.cpp src/dirtyJtag.cpp + src/efinix.cpp + src/efinixHexParser.cpp src/spiFlash.cpp src/rawParser.cpp src/usbBlaster.cpp @@ -77,6 +79,8 @@ set(OPENFPGALOADER_HEADERS src/anlogicCable.hpp src/cxxopts.hpp src/dirtyJtag.hpp + src/efinix.hpp + src/efinixHexParser.hpp src/progressBar.hpp src/rawParser.hpp src/usbBlaster.hpp diff --git a/src/efinix.cpp b/src/efinix.cpp new file mode 100644 index 0000000..2e9adba --- /dev/null +++ b/src/efinix.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2020 Gwenhael Goavec-Merou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "efinix.hpp" + +#include +#include + +#include +#include + +#include "display.hpp" +#include "efinixHexParser.hpp" +#include "ftdispi.hpp" +#include "device.hpp" +#include "rawParser.hpp" +#include "spiFlash.hpp" + +Efinix::Efinix(FtdiSpi* spi, const std::string &filename, + uint16_t rst_pin, uint16_t done_pin, + bool verbose): + Device(NULL, filename, verbose), _rst_pin(rst_pin), + _done_pin(done_pin) +{ + _spi = spi; + _spi->gpio_set_input(_done_pin); + _spi->gpio_set_output(_rst_pin); +} + +Efinix::~Efinix() +{} + +void Efinix::reset() +{ + uint32_t timeout = 1000; + _spi->gpio_clear(_rst_pin); + usleep(1000); + _spi->gpio_set(_rst_pin); + printInfo("Reset ", false); + do { + timeout--; + usleep(12000); + } while (((_spi->gpio_get(true) & _done_pin) == 0) || timeout > 0); + if (timeout == 0) + printError("FAIL"); + else + printSuccess("DONE"); +} + +void Efinix::program(unsigned int offset) +{ + uint32_t timeout = 1000; + + if (_filename == "") + return; + + ConfigBitstreamParser *bit; + if (_file_extension == "hex") { + bit = new EfinixHexParser(_filename, _verbose); + } else { + if (offset == 0) { + printError("Error: can't write raw data at the beginning of the flash"); + throw std::exception(); + } + bit = new RawParser(_filename, false); + } + printInfo("Parse file ", false); + if (bit->parse() == EXIT_SUCCESS) { + printSuccess("DONE"); + } else { + printError("FAIL"); + return; + } + + _spi->gpio_clear(_rst_pin); + + SPIFlash flash(reinterpret_cast(_spi), _verbose); + flash.reset(); + flash.power_up(); + + printf("%02x\n", flash.read_status_reg()); + flash.read_id(); + flash.erase_and_prog(offset, bit->getData(), bit->getLength() / 8); + + _spi->gpio_set(_rst_pin); + usleep(12000); + + printInfo("Wait for CDONE ", false); + do { + timeout--; + usleep(12000); + } while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0); + if (timeout == 0) + printError("FAIL"); + else + printSuccess("DONE"); +} diff --git a/src/efinix.hpp b/src/efinix.hpp new file mode 100644 index 0000000..f0bd9cb --- /dev/null +++ b/src/efinix.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 Gwenhael Goavec-Merou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SRC_EFINIX_HPP_ +#define SRC_EFINIX_HPP_ + +#include + +#include "device.hpp" +#include "ftdispi.hpp" + +class Efinix: public Device { + public: + Efinix(FtdiSpi *spi, const std::string &filename, + uint16_t rst_pin, uint16_t done_pin, + bool verbose); + ~Efinix(); + + void program(unsigned int offset = 0) override; + /* not supported in SPI Active mode */ + int idCode() override {return 0;} + void reset() override; + + private: + FtdiSpi *_spi; + uint16_t _rst_pin; + uint16_t _done_pin; +}; + +#endif // SRC_EFINIX_HPP_ diff --git a/src/efinixHexParser.cpp b/src/efinixHexParser.cpp new file mode 100644 index 0000000..08587db --- /dev/null +++ b/src/efinixHexParser.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 Gwenhael Goavec-Merou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "configBitstreamParser.hpp" +#include "display.hpp" +#include "efinixHexParser.hpp" + +using namespace std; + +EfinixHexParser::EfinixHexParser(const string &filename, bool reverseOrder): + ConfigBitstreamParser(filename, ConfigBitstreamParser::ASCII_MODE, + false), _reverseOrder(reverseOrder) +{} + +int EfinixHexParser::parse() +{ + char *c = new char[_file_size]; + _fd.read(c, sizeof(char) * _file_size); + + for (int offset = 0; offset < _file_size; offset += 3) { + char val; + sscanf(&c[offset], "%hhx", &val); + _bit_data += val; + } + _bit_length = _bit_data.size() * 8; + + delete c; + + return EXIT_SUCCESS; +} diff --git a/src/efinixHexParser.hpp b/src/efinixHexParser.hpp new file mode 100644 index 0000000..6e0c8fa --- /dev/null +++ b/src/efinixHexParser.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 Gwenhael Goavec-Merou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SRC_EFINIXHEXPARSER_HPP_ +#define SRC_EFINIXHEXPARSER_HPP_ + +#include + +#include "configBitstreamParser.hpp" + +/*! + * \file efinixHexParser + * \class EfinixHexParser + * \brief class used to read a raw data file + * \author Gwenhael Goavec-Merou + */ +class EfinixHexParser: public ConfigBitstreamParser { + public: + /*! + * \brief constructor + * \param[in] filename: raw file to read + * \param[in] reverseOrder: reverse each byte (LSB -> MSB, MSB -> LSB) + */ + EfinixHexParser(const std::string &filename, bool reverseOrder); + /*! + * \brief read full content of the file, fill the buffer + * \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwhise + */ + int parse() override; + + private: + bool _reverseOrder; /*!< tail if byte must be reversed */ +}; + +#endif // SRC_EFINIXHEXPARSER_HPP_ +