From e5545aa17eb74cbc6b194514326785fafcf48d17 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 8 Jul 2020 17:16:43 +0200 Subject: [PATCH] emc: add initial code to flash FPGA bitstream via PCIe --- fpga/include/villas/fpga/ips/emc.hpp | 9 ++ fpga/lib/ips/emc.cpp | 133 ++++++++++++++++++++++++++- fpga/thirdparty/libxil | 2 +- 3 files changed, 139 insertions(+), 5 deletions(-) diff --git a/fpga/include/villas/fpga/ips/emc.hpp b/fpga/include/villas/fpga/ips/emc.hpp index 490d1e61e..a1f418eae 100644 --- a/fpga/include/villas/fpga/ips/emc.hpp +++ b/fpga/include/villas/fpga/ips/emc.hpp @@ -27,6 +27,8 @@ #pragma once +#include + #include namespace villas { @@ -40,8 +42,15 @@ public: bool init(); + bool flash(uint32_t offset, const std::string &filename); + bool flash(uint32_t offset, uint32_t length, uint8_t *data); + + bool read(uint32_t offset, uint32_t length, uint8_t *data); + private: + XFlash xflash; + static constexpr char registerMemory[] = "Reg"; std::list getMemoryBlocks() const diff --git a/fpga/lib/ips/emc.cpp b/fpga/lib/ips/emc.cpp index 94e7e6418..ca56ded32 100644 --- a/fpga/lib/ips/emc.cpp +++ b/fpga/lib/ips/emc.cpp @@ -20,21 +20,146 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include +#include #include using namespace villas::fpga::ip; - // instantiate factory to make available to plugin infrastructure static EMCFactory factory; bool EMC::init() { - //const uintptr_t base = getBaseAddr(registerMemory); + int ret; + const uintptr_t base = getBaseAddr(registerMemory); + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL +#if XFL_TO_ASYNCMODE + /* Set Flash to Async mode. */ + if (FLASH_MEM_WIDTH == 1) { + WRITE_FLASH_8(FLASH_BASE_ADDRESS + ASYNC_ADDR, 0x60); + WRITE_FLASH_8(FLASH_BASE_ADDRESS + ASYNC_ADDR, 0x03); + } + else if (FLASH_MEM_WIDTH == 2) { + WRITE_FLASH_16(FLASH_BASE_ADDRESS + ASYNC_ADDR, + INTEL_CMD_CONFIG_REG_SETUP); + WRITE_FLASH_16(FLASH_BASE_ADDRESS + ASYNC_ADDR, + INTEL_CMD_CONFIG_REG_CONFIRM); + } +#endif +#endif + + ret = XFlash_Initialize(&xflash, base, 2, 0); + if (ret != XST_SUCCESS) + return false; + + return XFlash_IsReady(&xflash); +} + +bool +EMC::read(uint32_t offset, uint32_t length, uint8_t *data) +{ + int ret; + + /* + * Reset the Flash Device. This clears the ret registers and puts + * the device in Read mode. + */ + ret = XFlash_Reset(&xflash); + if (ret != XST_SUCCESS) + return false; + + /* + * Perform the read operation. + */ + ret = XFlash_Read(&xflash, offset, length, data); + if(ret != XST_SUCCESS) + return false; + + return false; +} + +// objcopy -I ihex -O binary somefile.mcs somefile.bin + +bool +EMC::flash(uint32_t offset, const std::string &filename) +{ + bool result; + uint32_t length; + uint8_t *buffer; + + std::ifstream is(filename, std::ios::binary); + + // get length of file: + is.seekg(0, std::ios::end); + length = is.tellg(); + + is.seekg (0, std::ios::beg); + // allocate memory: + + buffer = new uint8_t[length]; + is.read(reinterpret_cast(buffer), length); + is.close(); + + result = flash(offset, length, buffer); + + delete[] buffer; + + return result; +} + +/* Based on xilflash_readwrite_example.c */ +bool +EMC::flash(uint32_t offset, uint32_t length, uint8_t *data) +{ + int ret = XST_FAILURE; + uint32_t start = offset; + + uint8_t *verify_data = new uint8_t[length]; + + /* Reset the Flash Device. This clears the ret registers and puts + * the device in Read mode. */ + ret = XFlash_Reset(&xflash); + if (ret != XST_SUCCESS) + return false; + + /* Perform an unlock operation before the erase operation for the Intel + * Flash. The erase operation will result in an error if the block is + * locked. */ + if ((xflash.CommandSet == XFL_CMDSET_INTEL_STANDARD) || + (xflash.CommandSet == XFL_CMDSET_INTEL_EXTENDED) || + (xflash.CommandSet == XFL_CMDSET_INTEL_G18)) { + ret = XFlash_Unlock(&xflash, offset, 0); + if(ret != XST_SUCCESS) + return false; + } + + /* Perform the Erase operation. */ + ret = XFlash_Erase(&xflash, start, length); + if (ret != XST_SUCCESS) + return false; + + /* Perform the Write operation. */ + ret = XFlash_Write(&xflash, start, length, data); + if (ret != XST_SUCCESS) + return false; + + /* Perform the read operation. */ + ret = XFlash_Read(&xflash, start, length, verify_data); + if(ret != XST_SUCCESS) { + return false; + } + + /* Compare the data read against the data Written. */ + for (unsigned i = 0; i < length; i++) { + if (verify_data[i] != data[i]) + return false; + } + + delete[] verify_data; return true; } - diff --git a/fpga/thirdparty/libxil b/fpga/thirdparty/libxil index c11cc2fab..b622ddef4 160000 --- a/fpga/thirdparty/libxil +++ b/fpga/thirdparty/libxil @@ -1 +1 @@ -Subproject commit c11cc2fab5eea6bfa8b1412bb8bbd8680d3347d7 +Subproject commit b622ddef4315b7e8a56637d07aa2b26ba480d53a