mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-23 00:00:01 +01:00
166 lines
4 KiB
C++
166 lines
4 KiB
C++
/** AXI External Memory Controller (EMC)
|
|
*
|
|
* @author Steffen Vogel <post@steffenvogel.de>
|
|
* @copyright 2017-2020, Steffen Vogel
|
|
* @license GNU General Public License (version 3)
|
|
*
|
|
* VILLASfpga
|
|
*
|
|
* 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
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*********************************************************************************/
|
|
|
|
#include <iostream>
|
|
|
|
#include <villas/plugin.hpp>
|
|
#include <villas/fpga/ips/emc.hpp>
|
|
|
|
using namespace villas::fpga::ip;
|
|
|
|
// Instantiate factory to make available to plugin infrastructure
|
|
static EMCFactory factory;
|
|
|
|
bool
|
|
EMC::init()
|
|
{
|
|
int ret;
|
|
const uintptr_t base = getBaseAddr(registerMemory);
|
|
|
|
const int busWidth = 2;
|
|
|
|
#if defined(XPAR_XFL_DEVICE_FAMILY_INTEL) && XFL_TO_ASYNCMODE
|
|
// Set Flash to Async mode.
|
|
if (busWidth == 1) {
|
|
WRITE_FLASH_8(base + ASYNC_ADDR, 0x60);
|
|
WRITE_FLASH_8(base + ASYNC_ADDR, 0x03);
|
|
}
|
|
else if (busWidth == 2) {
|
|
WRITE_FLASH_16(base + ASYNC_ADDR, INTEL_CMD_CONFIG_REG_SETUP);
|
|
WRITE_FLASH_16(base + ASYNC_ADDR, INTEL_CMD_CONFIG_REG_CONFIRM);
|
|
}
|
|
#endif
|
|
|
|
ret = XFlash_Initialize(&xflash, base, busWidth, 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<char *>(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;
|
|
|
|
/* 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.
|
|
uint8_t *verify_data = new uint8_t[length];
|
|
ret = XFlash_Read(&xflash, start, length, verify_data);
|
|
if(ret != XST_SUCCESS) {
|
|
delete[] verify_data;
|
|
return false;
|
|
}
|
|
|
|
// Compare the data read against the data Written.
|
|
for (unsigned i = 0; i < length; i++) {
|
|
if (verify_data[i] != data[i]){
|
|
delete[] verify_data;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
delete[] verify_data;
|
|
|
|
return true;
|
|
}
|