2010-08-13 23:20:41 +00:00
|
|
|
//
|
2012-11-14 22:11:39 +00:00
|
|
|
// Copyright 2010-2012 Ettus Research LLC
|
2018-02-19 23:30:32 +00:00
|
|
|
// Copyright 2018 Ettus Research, a National Instruments Company
|
2010-08-13 23:20:41 +00:00
|
|
|
//
|
2018-02-19 23:30:32 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
2010-08-13 23:20:41 +00:00
|
|
|
//
|
|
|
|
|
|
2011-03-10 22:07:38 +00:00
|
|
|
#include <uhd/exception.hpp>
|
2010-08-13 23:20:41 +00:00
|
|
|
#include <uhd/transport/usb_control.hpp>
|
2020-03-02 23:25:13 +00:00
|
|
|
#include <uhd/utils/log.hpp>
|
|
|
|
|
#include <uhdlib/usrp/common/fx2_ctrl.hpp>
|
2016-10-31 21:30:52 +00:00
|
|
|
#include <stdint.h>
|
2020-03-02 23:25:13 +00:00
|
|
|
#include <boost/functional/hash.hpp>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <cstring>
|
2010-08-13 23:20:41 +00:00
|
|
|
#include <fstream>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <string>
|
2018-04-26 16:30:48 +00:00
|
|
|
#include <thread>
|
2020-03-02 23:25:13 +00:00
|
|
|
#include <vector>
|
2010-08-13 23:20:41 +00:00
|
|
|
|
|
|
|
|
using namespace uhd;
|
2011-06-14 22:32:11 +00:00
|
|
|
using namespace uhd::usrp;
|
2010-08-13 23:20:41 +00:00
|
|
|
|
|
|
|
|
#define FX2_FIRMWARE_LOAD 0xa0
|
|
|
|
|
|
2010-09-27 04:07:43 +00:00
|
|
|
static const bool load_img_msg = true;
|
|
|
|
|
|
2016-10-31 21:30:52 +00:00
|
|
|
typedef uint32_t hash_type;
|
2012-01-17 17:49:36 +00:00
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* Helper Functions
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
/*!
|
|
|
|
|
* Create a file hash
|
2011-03-10 22:07:38 +00:00
|
|
|
* The hash will be used to identify the loaded firmware and fpga image
|
2010-08-13 23:20:41 +00:00
|
|
|
* \param filename file used to generate hash value
|
|
|
|
|
* \return hash value in a size_t type
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
static hash_type generate_hash(const char* filename)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
|
|
|
|
std::ifstream file(filename);
|
2020-03-02 23:25:13 +00:00
|
|
|
if (not file) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error(std::string("cannot open input file ") + filename);
|
|
|
|
|
}
|
2010-08-13 23:20:41 +00:00
|
|
|
|
|
|
|
|
size_t hash = 0;
|
|
|
|
|
|
|
|
|
|
char ch;
|
|
|
|
|
while (file.get(ch)) {
|
|
|
|
|
boost::hash_combine(hash, ch);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (not file.eof()) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error(std::string("file error ") + filename);
|
|
|
|
|
}
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2011-03-10 22:07:38 +00:00
|
|
|
file.close();
|
2012-01-17 17:49:36 +00:00
|
|
|
return hash_type(hash);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
2011-03-10 22:07:38 +00:00
|
|
|
* Verify checksum of a Intel HEX record
|
2010-08-13 23:20:41 +00:00
|
|
|
* \param record a line from an Intel HEX file
|
2011-03-10 22:07:38 +00:00
|
|
|
* \return true if record is valid, false otherwise
|
2010-08-13 23:20:41 +00:00
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
static bool checksum(std::string* record)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
|
|
|
|
size_t len = record->length();
|
|
|
|
|
unsigned int i;
|
|
|
|
|
unsigned char sum = 0;
|
|
|
|
|
unsigned int val;
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < len; i += 2) {
|
|
|
|
|
std::istringstream(record->substr(i, 2)) >> std::hex >> val;
|
|
|
|
|
sum += val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sum == 0)
|
2020-03-02 23:25:13 +00:00
|
|
|
return true;
|
2010-08-13 23:20:41 +00:00
|
|
|
else
|
2020-03-02 23:25:13 +00:00
|
|
|
return false;
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* Parse Intel HEX record
|
|
|
|
|
*
|
|
|
|
|
* \param record a line from an Intel HEX file
|
|
|
|
|
* \param len output length of record
|
|
|
|
|
* \param addr output address
|
|
|
|
|
* \param type output type
|
|
|
|
|
* \param data output data
|
|
|
|
|
* \return true if record is sucessfully read, false on error
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
bool parse_record(std::string* record,
|
|
|
|
|
unsigned int& len,
|
|
|
|
|
unsigned int& addr,
|
|
|
|
|
unsigned int& type,
|
|
|
|
|
unsigned char* data)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
std::string _data;
|
|
|
|
|
unsigned int val;
|
|
|
|
|
|
|
|
|
|
if (record->substr(0, 1) != ":")
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
std::istringstream(record->substr(1, 2)) >> std::hex >> len;
|
|
|
|
|
std::istringstream(record->substr(3, 4)) >> std::hex >> addr;
|
|
|
|
|
std::istringstream(record->substr(7, 2)) >> std::hex >> type;
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (len > (2 * (record->length() - 9))) // sanity check to prevent buffer overrun
|
2013-11-27 20:11:23 +00:00
|
|
|
return false;
|
|
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
std::istringstream(record->substr(9 + 2 * i, 2)) >> std::hex >> val;
|
2020-03-02 23:25:13 +00:00
|
|
|
data[i] = (unsigned char)val;
|
2011-03-10 22:07:38 +00:00
|
|
|
}
|
2010-08-13 23:20:41 +00:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* USRP control implementation for device discovery and configuration
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
class fx2_ctrl_impl : public fx2_ctrl
|
|
|
|
|
{
|
2010-08-13 23:20:41 +00:00
|
|
|
public:
|
2011-06-14 22:32:11 +00:00
|
|
|
fx2_ctrl_impl(uhd::transport::usb_control::sptr ctrl_transport)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
|
|
|
|
_ctrl_transport = ctrl_transport;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_fx2_reset(void) override
|
2020-03-02 23:25:13 +00:00
|
|
|
{
|
2012-02-14 23:01:15 +00:00
|
|
|
unsigned char reset_y = 1;
|
|
|
|
|
unsigned char reset_n = 0;
|
|
|
|
|
usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1);
|
|
|
|
|
usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1);
|
2020-03-02 23:25:13 +00:00
|
|
|
// wait for things to settle
|
2018-04-26 16:30:48 +00:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
2012-02-14 23:01:15 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_load_firmware(std::string filestring, bool force) override
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
const char* filename = filestring.c_str();
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2012-01-17 17:49:36 +00:00
|
|
|
hash_type hash = generate_hash(filename);
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
hash_type loaded_hash;
|
|
|
|
|
usrp_get_firmware_hash(loaded_hash);
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (not force and (hash == loaded_hash))
|
|
|
|
|
return;
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// FIXME: verify types
|
2010-08-13 23:20:41 +00:00
|
|
|
unsigned int len;
|
|
|
|
|
unsigned int addr;
|
|
|
|
|
unsigned int type;
|
|
|
|
|
unsigned char data[512];
|
|
|
|
|
|
|
|
|
|
std::ifstream file;
|
|
|
|
|
file.open(filename, std::ifstream::in);
|
|
|
|
|
|
|
|
|
|
if (!file.good()) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_firmware: cannot open firmware input file");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned char reset_y = 1;
|
|
|
|
|
unsigned char reset_n = 0;
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// hit the reset line
|
|
|
|
|
if (load_img_msg)
|
|
|
|
|
UHD_LOGGER_INFO("FX2") << "Loading firmware image: " << filestring << "...";
|
2011-03-10 22:07:38 +00:00
|
|
|
usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1);
|
|
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
while (!file.eof()) {
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string record;
|
|
|
|
|
file >> record;
|
2011-03-10 22:07:38 +00:00
|
|
|
|
2013-12-12 02:01:41 +00:00
|
|
|
if (!(record.length() > 0))
|
|
|
|
|
continue;
|
2013-11-27 20:11:23 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// check for valid record
|
|
|
|
|
if (not checksum(&record)
|
|
|
|
|
or not parse_record(&record, len, addr, type, data)) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_firmware: bad record checksum");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// type 0x00 is data
|
2010-08-13 23:20:41 +00:00
|
|
|
if (type == 0x00) {
|
2011-03-10 22:07:38 +00:00
|
|
|
int ret = usrp_control_write(FX2_FIRMWARE_LOAD, addr, 0, data, len);
|
2020-03-02 23:25:13 +00:00
|
|
|
if (ret < 0)
|
|
|
|
|
throw uhd::io_error("usrp_load_firmware: usrp_control_write failed");
|
2011-03-10 22:07:38 +00:00
|
|
|
}
|
2020-03-02 23:25:13 +00:00
|
|
|
// type 0x01 is end
|
2010-08-13 23:20:41 +00:00
|
|
|
else if (type == 0x01) {
|
2020-03-02 23:25:13 +00:00
|
|
|
usrp_set_firmware_hash(hash); // set hash before reset
|
2011-03-10 22:07:38 +00:00
|
|
|
usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1);
|
2010-08-13 23:20:41 +00:00
|
|
|
file.close();
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// wait for things to settle
|
2018-04-26 16:30:48 +00:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
2020-03-02 23:25:13 +00:00
|
|
|
if (load_img_msg)
|
|
|
|
|
UHD_LOGGER_INFO("FX2") << "Firmware loaded";
|
2011-03-10 22:07:38 +00:00
|
|
|
return;
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
2020-03-02 23:25:13 +00:00
|
|
|
// type anything else is unhandled
|
2010-08-13 23:20:41 +00:00
|
|
|
else {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_firmware: unsupported record");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// file did not end
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_firmware: bad record");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_init(void) override
|
2020-03-02 23:25:13 +00:00
|
|
|
{
|
|
|
|
|
// disable
|
2011-01-17 23:18:46 +00:00
|
|
|
usrp_rx_enable(false);
|
|
|
|
|
usrp_tx_enable(false);
|
2011-05-02 06:09:20 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// toggle resets
|
2011-05-02 06:09:20 +00:00
|
|
|
usrp_rx_reset(true);
|
2011-01-17 23:18:46 +00:00
|
|
|
usrp_tx_reset(true);
|
2011-05-02 06:09:20 +00:00
|
|
|
usrp_rx_reset(false);
|
2011-01-17 23:18:46 +00:00
|
|
|
usrp_tx_reset(false);
|
|
|
|
|
}
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_load_fpga(std::string filestring) override
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
const char* filename = filestring.c_str();
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2012-01-17 17:49:36 +00:00
|
|
|
hash_type hash = generate_hash(filename);
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
hash_type loaded_hash;
|
|
|
|
|
usrp_get_fpga_hash(loaded_hash);
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (hash == loaded_hash)
|
|
|
|
|
return;
|
2010-08-13 23:20:41 +00:00
|
|
|
const int ep0_size = 64;
|
|
|
|
|
unsigned char buf[ep0_size];
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (load_img_msg)
|
|
|
|
|
UHD_LOGGER_INFO("FX2") << "Loading FPGA image: " << filestring << "...";
|
2010-09-24 01:32:06 +00:00
|
|
|
std::ifstream file;
|
|
|
|
|
file.open(filename, std::ios::in | std::ios::binary);
|
|
|
|
|
if (not file.good()) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_fpga: cannot open fpga input file");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
usrp_fpga_reset(true); // holding the fpga in reset while loading
|
2011-05-02 06:09:20 +00:00
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_BEGIN) < 0) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_fpga: fpga load error");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-28 17:24:53 +00:00
|
|
|
while (not file.eof()) {
|
2020-03-02 23:25:13 +00:00
|
|
|
file.read((char*)buf, sizeof(buf));
|
2011-07-09 00:55:49 +00:00
|
|
|
const std::streamsize n = file.gcount();
|
2020-03-02 23:25:13 +00:00
|
|
|
if (n == 0)
|
|
|
|
|
continue;
|
2016-10-31 21:30:52 +00:00
|
|
|
int ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, uint16_t(n));
|
2011-07-26 00:49:30 +00:00
|
|
|
if (ret < 0 or std::streamsize(ret) != n) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_fpga: fpga load error");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-03-10 22:07:38 +00:00
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_END) < 0) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_fpga: fpga load error");
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usrp_set_fpga_hash(hash);
|
2011-05-02 06:09:20 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
usrp_fpga_reset(false); // done loading, take fpga out of reset
|
2011-05-02 06:09:20 +00:00
|
|
|
|
2010-09-24 01:32:06 +00:00
|
|
|
file.close();
|
2020-03-02 23:25:13 +00:00
|
|
|
if (load_img_msg)
|
|
|
|
|
UHD_LOGGER_INFO("FX2") << "FPGA image loaded";
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_load_eeprom(std::string filestring) override
|
2010-08-31 23:44:30 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
if (load_img_msg)
|
|
|
|
|
UHD_LOGGER_INFO("FX2") << "Loading EEPROM image: " << filestring << "...";
|
|
|
|
|
const char* filename = filestring.c_str();
|
2016-10-31 21:30:52 +00:00
|
|
|
const uint16_t i2c_addr = 0x50;
|
2010-08-31 23:44:30 +00:00
|
|
|
|
|
|
|
|
unsigned int addr;
|
|
|
|
|
unsigned char data[256];
|
|
|
|
|
unsigned char sendbuf[17];
|
|
|
|
|
|
|
|
|
|
std::ifstream file;
|
|
|
|
|
file.open(filename, std::ifstream::in);
|
|
|
|
|
|
2011-03-10 22:07:38 +00:00
|
|
|
if (not file.good()) {
|
|
|
|
|
throw uhd::io_error("usrp_load_eeprom: cannot open EEPROM input file");
|
2010-08-31 23:44:30 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
file.read((char*)data, 256);
|
2011-07-09 00:55:49 +00:00
|
|
|
std::streamsize len = file.gcount();
|
2010-08-31 23:44:30 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (len == 256) {
|
2011-03-10 22:07:38 +00:00
|
|
|
throw uhd::io_error("usrp_load_eeprom: image size too large");
|
2010-08-31 23:44:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int pagesize = 16;
|
2020-03-02 23:25:13 +00:00
|
|
|
addr = 0;
|
|
|
|
|
while (len > 0) {
|
2011-03-10 22:07:38 +00:00
|
|
|
sendbuf[0] = addr;
|
2020-03-02 23:25:13 +00:00
|
|
|
memcpy(sendbuf + 1, &data[addr], len > pagesize ? pagesize : size_t(len));
|
|
|
|
|
int ret = usrp_i2c_write(
|
|
|
|
|
i2c_addr, sendbuf, (len > pagesize ? pagesize : size_t(len)) + 1);
|
2011-03-10 22:07:38 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
|
throw uhd::io_error("usrp_load_eeprom: usrp_i2c_write failed");
|
|
|
|
|
}
|
|
|
|
|
addr += pagesize;
|
|
|
|
|
len -= pagesize;
|
2018-04-26 16:30:48 +00:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
2010-08-31 23:44:30 +00:00
|
|
|
}
|
|
|
|
|
file.close();
|
2020-03-02 23:25:13 +00:00
|
|
|
if (load_img_msg)
|
|
|
|
|
UHD_LOGGER_INFO("FX2") << "EEPROM image loaded";
|
2010-08-31 23:44:30 +00:00
|
|
|
}
|
|
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
|
2011-03-10 22:07:38 +00:00
|
|
|
void usrp_set_led(int led_num, bool on)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2011-03-10 22:07:38 +00:00
|
|
|
UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_SET_LED, on, led_num) >= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
void usrp_get_firmware_hash(hash_type& hash)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
UHD_ASSERT_THROW(
|
|
|
|
|
usrp_control_read(
|
|
|
|
|
0xa0, USRP_HASH_SLOT_0_ADDR, 0, (unsigned char*)&hash, sizeof(hash))
|
|
|
|
|
>= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-01-17 17:49:36 +00:00
|
|
|
void usrp_set_firmware_hash(hash_type hash)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
UHD_ASSERT_THROW(
|
|
|
|
|
usrp_control_write(
|
|
|
|
|
0xa0, USRP_HASH_SLOT_0_ADDR, 0, (unsigned char*)&hash, sizeof(hash))
|
|
|
|
|
>= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
void usrp_get_fpga_hash(hash_type& hash)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
UHD_ASSERT_THROW(
|
|
|
|
|
usrp_control_read(
|
|
|
|
|
0xa0, USRP_HASH_SLOT_1_ADDR, 0, (unsigned char*)&hash, sizeof(hash))
|
|
|
|
|
>= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-01-17 17:49:36 +00:00
|
|
|
void usrp_set_fpga_hash(hash_type hash)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
UHD_ASSERT_THROW(
|
|
|
|
|
usrp_control_write(
|
|
|
|
|
0xa0, USRP_HASH_SLOT_1_ADDR, 0, (unsigned char*)&hash, sizeof(hash))
|
|
|
|
|
>= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_tx_enable(bool on) override
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2011-03-10 22:07:38 +00:00
|
|
|
UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_TX_ENABLE, on, 0) >= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_rx_enable(bool on) override
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2011-03-10 22:07:38 +00:00
|
|
|
UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RX_ENABLE, on, 0) >= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-03-10 22:07:38 +00:00
|
|
|
void usrp_tx_reset(bool on)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2011-03-10 22:07:38 +00:00
|
|
|
UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_TX_RESET, on, 0) >= 0);
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-03-10 22:07:38 +00:00
|
|
|
void usrp_rx_reset(bool on)
|
2011-01-17 23:18:46 +00:00
|
|
|
{
|
2011-03-10 22:07:38 +00:00
|
|
|
UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RX_RESET, on, 0) >= 0);
|
2011-01-17 23:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void usrp_fpga_reset(bool on) override
|
2011-05-02 06:09:20 +00:00
|
|
|
{
|
|
|
|
|
UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RESET, on, 0) >= 0);
|
|
|
|
|
}
|
2011-01-17 23:18:46 +00:00
|
|
|
|
2016-10-31 21:30:52 +00:00
|
|
|
int usrp_control_write(uint8_t request,
|
2020-03-02 23:25:13 +00:00
|
|
|
uint16_t value,
|
|
|
|
|
uint16_t index,
|
|
|
|
|
unsigned char* buff,
|
2021-01-08 08:33:36 +00:00
|
|
|
uint16_t length) override
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
return _ctrl_transport->submit(VRT_VENDOR_OUT, // bmReqeustType
|
|
|
|
|
request, // bRequest
|
|
|
|
|
value, // wValue
|
|
|
|
|
index, // wIndex
|
|
|
|
|
buff, // data
|
|
|
|
|
length); // wLength
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-31 21:30:52 +00:00
|
|
|
int usrp_control_read(uint8_t request,
|
2020-03-02 23:25:13 +00:00
|
|
|
uint16_t value,
|
|
|
|
|
uint16_t index,
|
|
|
|
|
unsigned char* buff,
|
2021-01-08 08:33:36 +00:00
|
|
|
uint16_t length) override
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
return _ctrl_transport->submit(VRT_VENDOR_IN, // bmReqeustType
|
|
|
|
|
request, // bRequest
|
|
|
|
|
value, // wValue
|
|
|
|
|
index, // wIndex
|
|
|
|
|
buff, // data
|
|
|
|
|
length); // wLength
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-31 21:30:52 +00:00
|
|
|
int usrp_control_write_cmd(uint8_t request, uint16_t value, uint16_t index)
|
2010-08-13 23:20:41 +00:00
|
|
|
{
|
|
|
|
|
return usrp_control_write(request, value, index, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
byte_vector_t read_eeprom(uint16_t addr, uint16_t offset, size_t num_bytes) override
|
2020-03-02 23:25:13 +00:00
|
|
|
{
|
2016-10-31 21:30:52 +00:00
|
|
|
this->write_i2c(addr, byte_vector_t(1, uint8_t(offset)));
|
2012-03-26 21:30:06 +00:00
|
|
|
return this->read_i2c(addr, num_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
int usrp_i2c_write(uint16_t i2c_addr, unsigned char* buf, uint16_t len) override
|
2010-08-31 23:44:30 +00:00
|
|
|
{
|
|
|
|
|
return usrp_control_write(VRQ_I2C_WRITE, i2c_addr, 0, buf, len);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
int usrp_i2c_read(uint16_t i2c_addr, unsigned char* buf, uint16_t len) override
|
2010-08-31 23:44:30 +00:00
|
|
|
{
|
|
|
|
|
return usrp_control_read(VRQ_I2C_READ, i2c_addr, 0, buf, len);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
static const bool iface_debug = false;
|
2011-06-30 04:16:28 +00:00
|
|
|
static const size_t max_i2c_data_bytes = 64;
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
void write_i2c(uint16_t addr, const byte_vector_t& bytes) override
|
2011-06-30 04:16:28 +00:00
|
|
|
{
|
|
|
|
|
UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes);
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
int ret =
|
|
|
|
|
this->usrp_i2c_write(addr, (unsigned char*)&bytes.front(), bytes.size());
|
2011-06-30 04:16:28 +00:00
|
|
|
|
|
|
|
|
if (iface_debug && (ret < 0))
|
|
|
|
|
uhd::runtime_error("USRP: failed i2c write");
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-08 08:33:36 +00:00
|
|
|
byte_vector_t read_i2c(uint16_t addr, size_t num_bytes) override
|
2011-06-30 04:16:28 +00:00
|
|
|
{
|
2020-03-02 23:25:13 +00:00
|
|
|
UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes);
|
2011-06-30 04:16:28 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
byte_vector_t bytes(num_bytes);
|
|
|
|
|
int ret = this->usrp_i2c_read(addr, (unsigned char*)&bytes.front(), num_bytes);
|
2011-06-30 04:16:28 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (iface_debug && ((ret < 0) || (unsigned)ret < (num_bytes)))
|
|
|
|
|
uhd::runtime_error("USRP: failed i2c read");
|
2011-06-30 04:16:28 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
return bytes;
|
2011-06-30 04:16:28 +00:00
|
|
|
}
|
2010-08-31 23:44:30 +00:00
|
|
|
|
2010-08-13 23:20:41 +00:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
uhd::transport::usb_control::sptr _ctrl_transport;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
2011-06-14 22:32:11 +00:00
|
|
|
* Public make function for fx2_ctrl interface
|
2010-08-13 23:20:41 +00:00
|
|
|
**********************************************************************/
|
2020-03-02 23:25:13 +00:00
|
|
|
fx2_ctrl::sptr fx2_ctrl::make(uhd::transport::usb_control::sptr ctrl_transport)
|
|
|
|
|
{
|
2011-06-14 22:32:11 +00:00
|
|
|
return sptr(new fx2_ctrl_impl(ctrl_transport));
|
2010-08-13 23:20:41 +00:00
|
|
|
}
|