aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2015-12-15 15:17:36 -0800
committerAshish Chaudhari <ashish@ettus.com>2015-12-15 15:17:36 -0800
commitf44f7f2ca7dbbd1a72f5b3d239856a1954569884 (patch)
tree310055d734a28063359b26f7cdc4d4704c517b9e
parent75ea07bd6d19494e018cd5c3109e1f85969b7ac6 (diff)
parent10178875a154e58af6c14774621776d13e7e3daa (diff)
downloaduhd-f44f7f2ca7dbbd1a72f5b3d239856a1954569884.tar.gz
uhd-f44f7f2ca7dbbd1a72f5b3d239856a1954569884.tar.bz2
uhd-f44f7f2ca7dbbd1a72f5b3d239856a1954569884.zip
Merge branch 'maint'
Conflicts: host/lib/usrp/b200/b200_impl.hpp host/lib/usrp/e300/e300_fpga_defs.hpp host/lib/usrp/x300/x300_fw_common.h
-rw-r--r--host/cmake/msvc/erllc_uhd_b205mini.inf175
-rw-r--r--host/lib/usrp/b200/b200_iface.cpp183
-rw-r--r--host/lib/usrp/b200/b200_iface.hpp45
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp60
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp9
-rw-r--r--host/lib/usrp/b200/b200_io_impl.cpp3
-rw-r--r--host/lib/usrp/b200/b200_regs.hpp2
-rw-r--r--host/lib/usrp/common/adf4001_ctrl.cpp8
-rw-r--r--host/lib/usrp/cores/time_core_3000.cpp13
-rw-r--r--host/lib/usrp/cores/time_core_3000.hpp2
-rw-r--r--host/lib/usrp/e300/e300_fpga_defs.hpp2
-rw-r--r--host/lib/usrp/e300/e300_impl.cpp27
-rw-r--r--host/lib/usrp/e300/e300_impl.hpp5
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp12
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp1
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp2
-rw-r--r--host/lib/usrp_clock/octoclock/CMakeLists.txt3
-rw-r--r--host/lib/usrp_clock/octoclock/kk_ihex.h191
-rw-r--r--host/lib/usrp_clock/octoclock/kk_ihex_license.txt20
-rw-r--r--host/lib/usrp_clock/octoclock/kk_ihex_read.c261
-rw-r--r--host/lib/usrp_clock/octoclock/kk_ihex_read.h119
-rw-r--r--host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp120
-rw-r--r--host/lib/utils/CMakeLists.txt1
-rw-r--r--host/lib/utils/ihex.cpp236
-rw-r--r--host/lib/utils/ihex.hpp79
-rw-r--r--host/utils/CMakeLists.txt3
-rw-r--r--host/utils/b2xx_fx3_utils.cpp5
-rw-r--r--host/utils/octoclock_firmware_burner.cpp22
-rw-r--r--host/utils/uhd-usrp.rules1
30 files changed, 701 insertions, 911 deletions
diff --git a/host/cmake/msvc/erllc_uhd_b205mini.inf b/host/cmake/msvc/erllc_uhd_b205mini.inf
new file mode 100644
index 000000000..1e5852656
--- /dev/null
+++ b/host/cmake/msvc/erllc_uhd_b205mini.inf
@@ -0,0 +1,175 @@
+; ======== libusb 1.0 (WinUSB) device driver ==========
+;
+; To customize this inf file for your own device
+;
+; 1. Change "DeviceName" with the name you want your device to appear with
+; on your system.
+;
+; 2. Change "VendorID" and "ProductID" according to those of your device.
+; If your device is plugged in, you can retrieve these values through the
+; Device Manager (regardless of whether the driver is installed or not).
+;
+; 3. Change "DeviceGUID" to a value that is unique on your system. For more
+; information and tools to help you generate your own GUIDs, see
+; http://en.wikipedia.org/wiki/Universally_Unique_Identifier.
+;
+; 4. Change "DeviceClassGUID" to reflect your USB Device Class.
+; The following Device Classes are listed for reference:
+; {745a17a0-74d3-11d0-b6fe-00a0c90f57da} : HID device
+; {78a1c341-4539-11d3-b88d-00c04fad5171} : Generic WinUSB device
+;
+; 5. (Optional) Change the "Date" string.
+;
+; Note 1: if you need to create a matching cat file for this inf, you can use
+; the inf2cat utility from the WinDDK, with the the following command:
+; inf2cat /driver:"path_to_your inf" /os:7_X86,7_X64,Vista_X86,Vista_X64
+;
+; Note 2: The co-installers provided in these files are version 1.9.
+; Please refer to:
+; http://blogs.msdn.com/iliast/archive/2008/03/10/why-do-we-need-wdf-coinstallers.aspx and
+; http://blogs.msdn.com/iliast/archive/2009/08/13/wdf-logo-requirements-regarding-coinstallers.aspx
+; for more information about co-installers and their versioning
+
+; ===================== Strings =======================
+
+[Strings]
+
+; =====================================================
+; ========= START USER CONFIGURABLE SECTION ===========
+; =====================================================
+
+DeviceName = "Ettus Research B205mini"
+; Make sure "VID_" and "PID_" are always part of the strings below
+VendorID = "VID_2500"
+ProductID = "PID_0022"
+DeviceGUID = "{211d89c8-92d7-11e5-be76-3c970eb8a18b}"
+DeviceClassGUID = "{78a1c341-4539-11d3-b88d-00c04fad5171}"
+; Date MUST be in MM/DD/YYYY format
+Date = "11/24/2015"
+
+; =====================================================
+; ========== END USER CONFIGURABLE SECTION ============
+; =====================================================
+
+ProviderName = "libusb 1.0"
+WinUSB_SvcDesc = "WinUSB Driver Service"
+DiskName = "libusb (WinUSB) Device Install Disk"
+ClassName = "libusb (WinUSB) devices"
+
+; ====================== Version ======================
+
+[Version]
+DriverVer = %Date%
+Signature = "$Windows NT$"
+Class = %ClassName%
+ClassGuid = %DeviceClassGUID%
+Provider = %ProviderName%
+CatalogFile = libusb_device.cat
+
+; =================== Class section ===================
+
+; Since the device is not a standard USB device, we define a new class for it.
+[ClassInstall32]
+Addreg = WinUSBDeviceClassReg
+
+[WinUSBDeviceClassReg]
+HKR,,,0,%ClassName%
+; -20 is for the USB icon
+HKR,,Icon,,-20
+
+; =========== Manufacturer/Models sections ============
+
+[Manufacturer]
+%ProviderName% = libusbDevice_WinUSB,NTx86,NTamd64
+
+[libusbDevice_WinUSB.NTx86]
+%DeviceName% = USB_Install, USB\%VendorID%&%ProductID%
+
+[libusbDevice_WinUSB.NTamd64]
+%DeviceName% = USB_Install, USB\%VendorID%&%ProductID%
+
+; ==================== Installation ===================
+
+; The Include and Needs directives in the USB_Install section are required for
+; installing WinUSB on Windows Vista systems. Windows XP systems ignore these
+; directives. These directives should not be modified.
+[USB_Install]
+Include=winusb.inf
+Needs=WINUSB.NT
+
+; The Include directive in the USB_Install.Services section includes the system-
+; supplied INF for WinUSB. This INF is installed by the WinUSB co-installer if
+; it is not already on the target system. The AddService directive specifies
+; WinUsb.sys as the device’s function driver. These directives should not be
+; modified.
+[USB_Install.Services]
+Include=winusb.inf
+AddService=WinUSB,0x00000002,WinUSB_ServiceInstall
+
+; The WinUSB_ServiceInstall section contains the data for installing WinUsb.sys
+; as a service. This section should not be modified.
+[WinUSB_ServiceInstall]
+DisplayName = %WinUSB_SvcDesc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\WinUSB.sys
+
+; The KmdfService directive installs WinUsb.sys as a kernel-mode service. The
+; referenced WinUSB_Install section specifies the KMDF library version.
+; Usually, the version can be derived from the WdfCoInstallerxxyyy.dll with
+; xx = major, yyy = minor
+[USB_Install.Wdf]
+KmdfService=WINUSB, WinUsb_Install
+
+[WinUSB_Install]
+KmdfLibraryVersion=1.9
+
+; USB_Install.HW is the key section in the INF. It specifies the device
+; interface globally unique identifier (GUID) for your device. The AddReg
+; directive puts the interface GUID in a standard registry value. When
+; WinUsb.sys is loaded as the device’s function driver, it reads the registry
+; value and uses the specified GUID to represent the device interface. You
+; should replace the GUID in this example with one that you create specifically
+; for your device. If the protocols for the device change, you should create a
+; new device interface GUID.
+[USB_Install.HW]
+AddReg=Dev_AddReg
+
+[Dev_AddReg]
+HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID%
+
+; The USB_Install.CoInstallers section, including the referenced AddReg and
+; CopyFiles sections, contains data and instructions to install the WinUSB and
+; KMDF co installers and associate them with the device. Most USB devices can
+; use these sections and directives without modification.
+[USB_Install.CoInstallers]
+AddReg=CoInstallers_AddReg
+CopyFiles=CoInstallers_CopyFiles
+
+[CoInstallers_AddReg]
+HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller","WinUSBCoInstaller2.dll"
+
+[CoInstallers_CopyFiles]
+WinUSBCoInstaller2.dll
+WdfCoInstaller01009.dll
+
+[DestinationDirs]
+CoInstallers_CopyFiles=11
+
+; =============== Source Media Section ================
+
+; The x86 and x64 versions of Windows have separate co installers. This example
+; stores them on the installation disk in folders that are named x86 and amd64
+[SourceDisksNames]
+1 = %DiskName%,,,\x86
+2 = %DiskName%,,,\amd64
+
+[SourceDisksFiles.x86]
+WinUSBCoInstaller2.dll=1
+WdfCoInstaller01009.dll=1
+
+[SourceDisksFiles.amd64]
+WinUSBCoInstaller2.dll=2
+WdfCoInstaller01009.dll=2
+
diff --git a/host/lib/usrp/b200/b200_iface.cpp b/host/lib/usrp/b200/b200_iface.cpp
index 4754a6357..207c418fc 100644
--- a/host/lib/usrp/b200/b200_iface.cpp
+++ b/host/lib/usrp/b200/b200_iface.cpp
@@ -17,6 +17,7 @@
#include "b200_iface.hpp"
+#include "../../utils/ihex.hpp"
#include <uhd/config.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/utils/log.hpp>
@@ -87,7 +88,7 @@ typedef boost::uint32_t hash_type;
**********************************************************************/
/*!
* Create a file hash
- * The hash will be used to identify the loaded firmware and fpga image
+ * The hash will be used to identify the loaded fpga image
* \param filename file used to generate hash value
* \return hash value in a uint32_t type
*/
@@ -125,66 +126,6 @@ static hash_type generate_hash(const char *filename)
}
-/*!
- * Verify checksum of a Intel HEX record
- * \param record a line from an Intel HEX file
- * \return true if record is valid, false otherwise
- */
-bool checksum(const std::string& record) {
-
- 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)
- return true;
- else
- return false;
-}
-
-
-/*!
- * 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
- */
-bool parse_record(const std::string& record, boost::uint16_t &len, \
- boost::uint16_t &addr, boost::uint16_t &type, unsigned char* data) {
-
- 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;
-
- if (len > (2 * (record.length() - 9))) // sanity check to prevent buffer overrun
- return false;
-
- for (i = 0; i < len; i++) {
- std::istringstream(record.substr(9 + 2 * i, 2)) >> std::hex >> val;
- data[i] = (unsigned char) val;
- }
-
- return true;
-}
-
-
/***********************************************************************
* The implementation class
**********************************************************************/
@@ -270,109 +211,31 @@ public:
void load_firmware(const std::string filestring, UHD_UNUSED(bool force) = false)
{
- const char *filename = filestring.c_str();
-
- /* Fields used in each USB control transfer. */
- boost::uint16_t len = 0;
- boost::uint16_t type = 0;
- boost::uint16_t lower_address_bits = 0x0000;
- unsigned char data[512];
-
- /* Can be set by the Intel HEX record 0x04, used for all 0x00 records
- * thereafter. Note this field takes the place of the 'index' parameter in
- * libusb calls, and is necessary for FX3's 32-bit addressing. */
- boost::uint16_t upper_address_bits = 0x0000;
-
- std::ifstream file;
- file.open(filename, std::ifstream::in);
-
- if(!file.good()) {
- throw uhd::io_error("fx3_load_firmware: cannot open firmware input file");
+ if (load_img_msg)
+ UHD_MSG(status) << "Loading firmware image: "
+ << filestring << "..." << std::flush;
+
+ ihex_reader file_reader(filestring);
+ try {
+ file_reader.read(
+ boost::bind(
+ &b200_iface_impl::fx3_control_write, this,
+ FX3_FIRMWARE_LOAD, _1, _2, _3, _4, 0
+ )
+ );
+ } catch (const uhd::io_error &e) {
+ throw uhd::io_error(str(boost::format("Could not load firmware: \n%s") % e.what()));
}
- if (load_img_msg) UHD_MSG(status) << "Loading firmware image: " \
- << filestring << "..." << std::flush;
-
- while (!file.eof()) {
- boost::int32_t ret = 0;
- std::string record;
- file >> record;
-
- if (!(record.length() > 0))
- continue;
-
- /* Check for valid Intel HEX record. */
- if (!checksum(record) || !parse_record(record, len, \
- lower_address_bits, type, data)) {
- throw uhd::io_error("fx3_load_firmware: bad intel hex record checksum");
- }
-
- /* Type 0x00: Data. */
- if (type == 0x00) {
- ret = fx3_control_write(FX3_FIRMWARE_LOAD, \
- lower_address_bits, upper_address_bits, data, len);
-
- if (ret < 0) {
- throw uhd::io_error("usrp_load_firmware: usrp_control_write failed");
- }
- }
-
- /* Type 0x01: EOF. */
- else if (type == 0x01) {
- if (lower_address_bits != 0x0000 || len != 0 ) {
- throw uhd::io_error("fx3_load_firmware: For EOF record, address must be 0, length must be 0.");
- }
-
- //TODO
- //usrp_set_firmware_hash(hash); //set hash before reset
-
- /* Successful termination! */
- file.close();
+ UHD_MSG(status) << std::endl;
- /* Let the system settle. */
- boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
- return;
- }
-
- /* Type 0x04: Extended Linear Address Record. */
- else if (type == 0x04) {
- if (lower_address_bits != 0x0000 || len != 2 ) {
- throw uhd::io_error("fx3_load_firmware: For ELA record, address must be 0, length must be 2.");
- }
-
- upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\
- + ((boost::uint16_t)(data[1] & 0x00FF));
- }
-
- /* Type 0x05: Start Linear Address Record. */
- else if (type == 0x05) {
- if (lower_address_bits != 0x0000 || len != 4 ) {
- throw uhd::io_error("fx3_load_firmware: For SLA record, address must be 0, length must be 4.");
- }
-
- /* The firmware load is complete. We now need to tell the CPU
- * to jump to an execution address start point, now contained within
- * the data field. Parse these address bits out, and then push the
- * instruction. */
- upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\
- + ((boost::uint16_t)(data[1] & 0x00FF));
- lower_address_bits = ((boost::uint16_t)((data[2] & 0x00FF) << 8))\
- + ((boost::uint16_t)(data[3] & 0x00FF));
-
- fx3_control_write(FX3_FIRMWARE_LOAD, lower_address_bits, \
- upper_address_bits, 0, 0);
-
- if (load_img_msg) UHD_MSG(status) << " done" << std::endl;
- }
-
- /* If we receive an unknown record type, error out. */
- else {
- throw uhd::io_error("fx3_load_firmware: unsupported record type.");
- }
- }
+ //TODO
+ //usrp_set_firmware_hash(hash); //set hash before reset
- /* There was no valid EOF. */
- throw uhd::io_error("fx3_load_firmware: No EOF record found.");
+ /* Success! Let the system settle. */
+ // TODO: Replace this with a polling loop in the FX3, or find out
+ // what the actual, correct timeout value is.
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}
void reset_fx3(void) {
diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp
index 19ec561fa..e45c78d49 100644
--- a/host/lib/usrp/b200/b200_iface.hpp
+++ b/host/lib/usrp/b200/b200_iface.hpp
@@ -30,25 +30,28 @@
enum b200_product_t {
B200,
B210,
- B205
+ B200MINI,
+ B205MINI
};
// These are actual USB PIDs (not Ettus Product IDs)
-const static boost::uint16_t B200_VENDOR_ID = 0x2500;
-const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923;
-const static boost::uint16_t B200_PRODUCT_ID = 0x0020;
-const static boost::uint16_t B205_PRODUCT_ID = 0x0021;
-const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813;
-const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814;
-const static boost::uint16_t FX3_VID = 0x04b4;
-const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3;
-const static boost::uint16_t FX3_REENUM_PID = 0x00f0;
+const static boost::uint16_t B200_VENDOR_ID = 0x2500;
+const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923;
+const static boost::uint16_t B200_PRODUCT_ID = 0x0020;
+const static boost::uint16_t B200MINI_PRODUCT_ID = 0x0021;
+const static boost::uint16_t B205MINI_PRODUCT_ID = 0x0022;
+const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813;
+const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814;
+const static boost::uint16_t FX3_VID = 0x04b4;
+const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3;
+const static boost::uint16_t FX3_REENUM_PID = 0x00f0;
//! Map the USB PID to the product (only for PIDs that map to a single product)
static const uhd::dict<boost::uint16_t, b200_product_t> B2XX_PID_TO_PRODUCT = boost::assign::map_list_of
- (B200_PRODUCT_NI_ID, B200)
- (B210_PRODUCT_NI_ID, B210)
- (B205_PRODUCT_ID, B205)
+ (B200_PRODUCT_NI_ID, B200)
+ (B210_PRODUCT_NI_ID, B210)
+ (B200MINI_PRODUCT_ID, B200MINI)
+ (B205MINI_PRODUCT_ID, B205MINI)
;
static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex";
@@ -61,21 +64,25 @@ static const uhd::dict<boost::uint16_t, b200_product_t> B2XX_PRODUCT_ID = boost:
(0x0002, B210)
(0x7738, B210)
(B210_PRODUCT_NI_ID, B210)
- (0x0003, B205)
- (0x7739, B205)
+ (0x0003, B200MINI)
+ (0x7739, B200MINI)
+ (0x0004, B205MINI)
+ (0x773a, B205MINI)
;
static const uhd::dict<b200_product_t, std::string> B2XX_STR_NAMES = boost::assign::map_list_of
- (B200, "B200")
- (B210, "B210")
- (B205, "B200mini")
+ (B200, "B200")
+ (B210, "B210")
+ (B200MINI, "B200mini")
+ (B205MINI, "B205mini")
;
static const uhd::dict<b200_product_t, std::string> B2XX_FPGA_FILE_NAME = boost::assign::map_list_of
(B200, "usrp_b200_fpga.bin")
(B210, "usrp_b210_fpga.bin")
- (B205, "usrp_b200mini_fpga.bin")
+ (B200MINI, "usrp_b200mini_fpga.bin")
+ (B205MINI, "usrp_b205mini_fpga.bin")
;
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 3aaf28ab3..62690f09f 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -75,9 +75,9 @@ public:
};
// B205
-class b205_ad9361_client_t : public ad9361_params {
+class b2xxmini_ad9361_client_t : public ad9361_params {
public:
- ~b205_ad9361_client_t() {}
+ ~b2xxmini_ad9361_client_t() {}
double get_band_edge(frequency_band_t band) {
switch (band) {
case AD9361_RX_BAND0: return 0; // Set these all to
@@ -319,7 +319,8 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
else if (specified_vid)
{
vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200_PRODUCT_ID));
- vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B205_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200MINI_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B205MINI_PRODUCT_ID));
vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200_PRODUCT_NI_ID));
vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B210_PRODUCT_NI_ID));
}
@@ -333,7 +334,8 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
else
{
vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID));
- vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200MINI_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205MINI_PRODUCT_ID));
vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID));
vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID));
}
@@ -387,7 +389,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
UHD_MSG(status) << "Detected Device: " << B2XX_STR_NAMES[_product] << std::endl;
- _gpsdo_capable = (_product != B205);
+ _gpsdo_capable = (not (_product == B200MINI or _product == B205MINI));
////////////////////////////////////////////////////////////////////
// Set up frontend mapping
@@ -406,7 +408,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
_fe2 = 0;
_gpio_state.swap_atr = 1;
// Unswapped setup:
- if (_product == B205 or (_product == B200 and _revision >= 5)) {
+ if (_product == B200MINI or _product == B205MINI or (_product == B200 and _revision >= 5)) {
_fe1 = 0; //map radio0 to FE1
_fe2 = 1; //map radio1 to FE2
_gpio_state.swap_atr = 0; // ATRs for radio0 are mapped to FE1
@@ -513,7 +515,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
////////////////////////////////////////////////////////////////////
_tree->create<std::string>("/name").set("B-Series Device");
_tree->create<std::string>(mb_path / "name").set(product_name);
- _tree->create<std::string>(mb_path / "codename").set((_product == B205) ? "Pixie" : "Sasquatch");
+ _tree->create<std::string>(mb_path / "codename").set((_product == B200MINI or _product == B205MINI) ? "Pixie" : "Sasquatch");
////////////////////////////////////////////////////////////////////
// Create data transport
@@ -541,7 +543,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
// create time and clock control objects
////////////////////////////////////////////////////////////////////
_spi_iface = b200_local_spi_core::make(_local_ctrl);
- if (_product != B205) {
+ if (not (_product == B200MINI or _product == B205MINI)) {
_adf4001_iface = boost::make_shared<b200_ref_pll_ctrl>(_spi_iface);
}
@@ -550,13 +552,13 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
////////////////////////////////////////////////////////////////////
UHD_MSG(status) << "Initialize CODEC control..." << std::endl;
ad9361_params::sptr client_settings;
- if (_product == B205) {
- client_settings = boost::make_shared<b205_ad9361_client_t>();
+ if (_product == B200MINI or _product == B205MINI) {
+ client_settings = boost::make_shared<b2xxmini_ad9361_client_t>();
} else {
client_settings = boost::make_shared<b200_ad9361_client_t>();
}
_codec_ctrl = ad9361_ctrl::make_spi(client_settings, _spi_iface, AD9361_SLAVENO);
-
+
////////////////////////////////////////////////////////////////////
// create codec control objects
////////////////////////////////////////////////////////////////////
@@ -624,15 +626,18 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
//register time now and pps onto available radio cores
_tree->create<time_spec_t>(mb_path / "time" / "now")
- .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64));
+ .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64))
+ .subscribe(boost::bind(&b200_impl::set_time, this, _1))
+ .set(0.0);
+ //re-sync the times when the tick rate changes
+ _tree->access<double>(mb_path / "tick_rate")
+ .subscribe(boost::bind(&b200_impl::sync_times, this));
_tree->create<time_spec_t>(mb_path / "time" / "pps")
.publish(boost::bind(&time_core_3000::get_time_last_pps, _radio_perifs[0].time64));
- for (size_t i = 0; i < _radio_perifs.size(); i++)
+ BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
{
- _tree->access<time_spec_t>(mb_path / "time" / "now")
- .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[i].time64, _1));
_tree->access<time_spec_t>(mb_path / "time" / "pps")
- .subscribe(boost::bind(&time_core_3000::set_time_next_pps, _radio_perifs[i].time64, _1));
+ .subscribe(boost::bind(&time_core_3000::set_time_next_pps, perif.time64, _1));
}
//setup time source props
@@ -945,7 +950,7 @@ void b200_impl::check_fpga_compat(void)
if (signature != 0xACE0BA5E) throw uhd::runtime_error(
"b200::check_fpga_compat signature register readback failed");
- const boost::uint16_t expected = (_product == B205 ? B205_FPGA_COMPAT_NUM : B200_FPGA_COMPAT_NUM);
+ const boost::uint16_t expected = ((_product == B200MINI or _product == B205MINI) ? B205_FPGA_COMPAT_NUM : B200_FPGA_COMPAT_NUM);
if (compat_major != expected)
{
throw uhd::runtime_error(str(boost::format(
@@ -970,7 +975,7 @@ void b200_impl::set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &mb_eeprom)
void b200_impl::update_clock_source(const std::string &source)
{
// For B205, ref_sel selects whether or not to lock to the external clock source
- if (_product == B205)
+ if (_product == B200MINI or _product == B205MINI)
{
if (source == "external" and _time_source == EXTERNAL)
{
@@ -1032,7 +1037,7 @@ void b200_impl::update_clock_source(const std::string &source)
void b200_impl::update_time_source(const std::string &source)
{
- if (_product == B205 and source == "external" and _gpio_state.ref_sel == 1)
+ if ((_product == B200MINI or _product == B205MINI) and source == "external" and _gpio_state.ref_sel == 1)
{
throw uhd::value_error("external reference cannot be both a time source and a clock source");
}
@@ -1052,11 +1057,24 @@ void b200_impl::update_time_source(const std::string &source)
throw uhd::key_error("update_time_source: unknown source: " + source);
if (_time_source != value)
{
- _local_ctrl->poke32(TOREG(SR_CORE_PPS_SEL), value);
+ _local_ctrl->poke32(TOREG(SR_CORE_SYNC), value);
_time_source = value;
}
}
+void b200_impl::set_time(const uhd::time_spec_t& t)
+{
+ BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
+ perif.time64->set_time_sync(t);
+ _local_ctrl->poke32(TOREG(SR_CORE_SYNC), 1 << 2 | boost::uint32_t(_time_source));
+ _local_ctrl->poke32(TOREG(SR_CORE_SYNC), _time_source);
+}
+
+void b200_impl::sync_times()
+{
+ set_time(_radio_perifs[0].time64->get_time_now());
+}
+
/***********************************************************************
* GPIO setup
**********************************************************************/
@@ -1064,7 +1082,7 @@ void b200_impl::update_time_source(const std::string &source)
void b200_impl::update_bandsel(const std::string& which, double freq)
{
// B205 does not have bandsels
- if (_product == B205) {
+ if (_product == B200MINI or _product == B205MINI) {
return;
}
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index b406572fb..08ae68e9a 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -49,8 +49,8 @@
#include "recv_packet_demuxer_3000.hpp"
static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 8;
static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0;
-static const boost::uint16_t B200_FPGA_COMPAT_NUM = 12;
-static const boost::uint16_t B205_FPGA_COMPAT_NUM = 3;
+static const boost::uint16_t B200_FPGA_COMPAT_NUM = 13;
+static const boost::uint16_t B205_FPGA_COMPAT_NUM = 4;
static const double B200_BUS_CLOCK_RATE = 100e6;
static const boost::uint32_t B200_GPSDO_ST_NONE = 0x83;
static const size_t B200_MAX_RATE_USB2 = 53248000; // bytes/s
@@ -95,7 +95,8 @@ static const unsigned char B200_USB_DATA_SEND_ENDPOINT = 2;
static std::vector<uhd::transport::usb_device_handle::vid_pid_pair_t> b200_vid_pid_pairs =
boost::assign::list_of
(uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID))
- (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205_PRODUCT_ID))
+ (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200MINI_PRODUCT_ID))
+ (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205MINI_PRODUCT_ID))
(uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID))
(uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID))
;
@@ -167,6 +168,8 @@ private:
uhd::usrp::subdev_spec_t coerce_subdev_spec(const uhd::usrp::subdev_spec_t &);
void update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &);
void update_time_source(const std::string &);
+ void set_time(const uhd::time_spec_t&);
+ void sync_times(void);
void update_clock_source(const std::string &);
void update_bandsel(const std::string& which, double freq);
void update_antenna_sel(const size_t which, const std::string &ant);
diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp
index 41b4b8a74..279901208 100644
--- a/host/lib/usrp/b200/b200_io_impl.cpp
+++ b/host/lib/usrp/b200/b200_io_impl.cpp
@@ -227,7 +227,8 @@ uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_s
//
// Any other spec is probably illegal and will be caught by
// validate_subdev_spec().
- if (spec.size() and (_product == B200 or _product == B205) and spec[0].sd_name == "B") {
+ if (spec.size() and (_product == B200 or _product == B200MINI or _product == B205MINI) and spec[0].sd_name == "B")
+ {
spec[0].sd_name = "A";
}
return spec;
diff --git a/host/lib/usrp/b200/b200_regs.hpp b/host/lib/usrp/b200/b200_regs.hpp
index 8f2dd03f3..e9ab81bae 100644
--- a/host/lib/usrp/b200/b200_regs.hpp
+++ b/host/lib/usrp/b200/b200_regs.hpp
@@ -28,7 +28,7 @@ localparam SR_CORE_SPI = 8;
localparam SR_CORE_MISC = 16;
localparam SR_CORE_COMPAT = 24;
localparam SR_CORE_GPSDO_ST = 40;
-localparam SR_CORE_PPS_SEL = 48;
+localparam SR_CORE_SYNC = 48;
localparam RB32_CORE_SPI = 8;
localparam RB32_CORE_MISC = 16;
localparam RB32_CORE_STATUS = 20;
diff --git a/host/lib/usrp/common/adf4001_ctrl.cpp b/host/lib/usrp/common/adf4001_ctrl.cpp
index a7510c272..001b68b7a 100644
--- a/host/lib/usrp/common/adf4001_ctrl.cpp
+++ b/host/lib/usrp/common/adf4001_ctrl.cpp
@@ -81,7 +81,7 @@ boost::uint32_t adf4001_regs_t::get_reg(boost::uint8_t addr) {
reg |= (boost::uint32_t(timer_counter_control) & 0x00000F) << 11;
reg |= (boost::uint32_t(charge_pump_current_1) & 0x000007) << 15;
reg |= (boost::uint32_t(charge_pump_current_2) & 0x000007) << 18;
- reg |= (boost::uint32_t(power_down) & 0x000002) << 21;
+ reg |= (boost::uint32_t(power_down) & 0x000002) << 20;
break;
default:
break;
@@ -128,15 +128,15 @@ void adf4001_ctrl::set_lock_to_ext_ref(bool external) {
void adf4001_ctrl::program_regs(void) {
//no control over CE, only LE, therefore we use the initialization latch method
write_reg(3);
- boost::this_thread::sleep(boost::posix_time::microseconds(1));
+
+ //conduct a function latch (2)
+ write_reg(2);
//write R counter latch (0)
write_reg(0);
- boost::this_thread::sleep(boost::posix_time::microseconds(1));
//write N counter latch (1)
write_reg(1);
- boost::this_thread::sleep(boost::posix_time::microseconds(1));
}
diff --git a/host/lib/usrp/cores/time_core_3000.cpp b/host/lib/usrp/cores/time_core_3000.cpp
index ffae5dc0d..694edf31c 100644
--- a/host/lib/usrp/cores/time_core_3000.cpp
+++ b/host/lib/usrp/cores/time_core_3000.cpp
@@ -24,8 +24,9 @@
#define REG_TIME_LO _base + 4
#define REG_TIME_CTRL _base + 8
-#define CTRL_LATCH_TIME_PPS (1 << 1)
-#define CTRL_LATCH_TIME_NOW (1 << 0)
+#define CTRL_LATCH_TIME_NOW (1 << 0)
+#define CTRL_LATCH_TIME_PPS (1 << 1)
+#define CTRL_LATCH_TIME_SYNC (1 << 2)
using namespace uhd;
@@ -99,6 +100,14 @@ struct time_core_3000_impl : time_core_3000
_iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_NOW);
}
+ void set_time_sync(const uhd::time_spec_t &time)
+ {
+ const boost::uint64_t ticks = time.to_ticks(_tick_rate);
+ _iface->poke32(REG_TIME_HI, boost::uint32_t(ticks >> 32));
+ _iface->poke32(REG_TIME_LO, boost::uint32_t(ticks >> 0));
+ _iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_SYNC);
+ }
+
void set_time_next_pps(const uhd::time_spec_t &time)
{
const boost::uint64_t ticks = time.to_ticks(_tick_rate);
diff --git a/host/lib/usrp/cores/time_core_3000.hpp b/host/lib/usrp/cores/time_core_3000.hpp
index 7463386ba..7dde4e797 100644
--- a/host/lib/usrp/cores/time_core_3000.hpp
+++ b/host/lib/usrp/cores/time_core_3000.hpp
@@ -53,6 +53,8 @@ public:
virtual void set_time_now(const uhd::time_spec_t &time) = 0;
+ virtual void set_time_sync(const uhd::time_spec_t &time) = 0;
+
virtual void set_time_next_pps(const uhd::time_spec_t &time) = 0;
};
diff --git a/host/lib/usrp/e300/e300_fpga_defs.hpp b/host/lib/usrp/e300/e300_fpga_defs.hpp
index dcfb05021..594461518 100644
--- a/host/lib/usrp/e300/e300_fpga_defs.hpp
+++ b/host/lib/usrp/e300/e300_fpga_defs.hpp
@@ -21,7 +21,7 @@ namespace uhd { namespace usrp { namespace e300 { namespace fpga {
static const size_t NUM_RADIOS = 2;
-static const boost::uint32_t COMPAT_MAJOR = 13;
+static const boost::uint32_t COMPAT_MAJOR = 14;
static const boost::uint32_t COMPAT_MINOR = 0;
}}}} // namespace
diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp
index c82ab3d0e..3242a7fe8 100644
--- a/host/lib/usrp/e300/e300_impl.cpp
+++ b/host/lib/usrp/e300/e300_impl.cpp
@@ -175,7 +175,7 @@ device_addrs_t e300_find(const device_addr_t &multi_dev_hint)
device_addr_t new_hint = hint;
new_hint["addr"] = if_addrs.bcast;
- // call discover with the new hint ad append results
+ // call discover with the new hint and append results
device_addrs_t new_e300_addrs = e300_find(new_hint);
e300_addrs.insert(e300_addrs.begin(),
new_e300_addrs.begin(), new_e300_addrs.end());
@@ -529,8 +529,11 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
////////////////////////////////////////////////////////////////////
_tree->create<time_spec_t>(mb_path / "time" / "now")
.publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64))
- .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[0].time64, _1))
- .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[1].time64, _1));
+ .subscribe(boost::bind(&e300_impl::_set_time, this, _1))
+ .set(0.0);
+ //re-sync the times when the tick rate changes
+ _tree->access<double>(mb_path / "tick_rate")
+ .subscribe(boost::bind(&e300_impl::_sync_times, this));
_tree->create<time_spec_t>(mb_path / "time" / "pps")
.publish(boost::bind(&time_core_3000::get_time_last_pps, _radio_perifs[0].time64))
.subscribe(boost::bind(&time_core_3000::set_time_next_pps, _radio_perifs[0].time64, _1))
@@ -796,6 +799,21 @@ void e300_impl::_update_time_source(const std::string &source)
_update_gpio_state();
}
+void e300_impl::_set_time(const uhd::time_spec_t& t)
+{
+ BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
+ perif.time64->set_time_sync(t);
+ _misc.time_sync = 1;
+ _update_gpio_state();
+ _misc.time_sync = 0;
+ _update_gpio_state();
+}
+
+void e300_impl::_sync_times()
+{
+ _set_time(_radio_perifs[0].time64->get_time_now());
+}
+
size_t e300_impl::_get_axi_dma_channel(
boost::uint8_t destination,
boost::uint8_t prefix)
@@ -1081,7 +1099,8 @@ void e300_impl::_update_gpio_state(void)
| (_misc.tx_bandsels << gpio_t::TX_BANDSEL)
| (_misc.rx_bandsel_a << gpio_t::RX_BANDSELA)
| (_misc.rx_bandsel_b << gpio_t::RX_BANDSELB)
- | (_misc.rx_bandsel_c << gpio_t::RX_BANDSELC);
+ | (_misc.rx_bandsel_c << gpio_t::RX_BANDSELC)
+ | (_misc.time_sync << gpio_t::TIME_SYNC);
_global_regs->poke32(global_regs::SR_CORE_MISC, misc_reg);
}
diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp
index 9b39c7468..1bf5cb950 100644
--- a/host/lib/usrp/e300/e300_impl.hpp
+++ b/host/lib/usrp/e300/e300_impl.hpp
@@ -200,6 +200,8 @@ private: // types
boost::uint32_t rx_bandsel_b;
boost::uint32_t rx_bandsel_c;
+ boost::uint32_t time_sync;
+
static const size_t PPS_SEL = 0;
static const size_t MIMO = 2;
static const size_t CODEC_ARST = 3;
@@ -207,6 +209,7 @@ private: // types
static const size_t RX_BANDSELA = 7;
static const size_t RX_BANDSELB = 13;
static const size_t RX_BANDSELC = 17;
+ static const size_t TIME_SYNC = 21;
};
private: // methods
@@ -257,6 +260,8 @@ private: // methods
void _update_time_source(const std::string &source);
void _update_clock_source(const std::string &);
+ void _set_time(const uhd::time_spec_t&);
+ void _sync_times(void);
void _update_subdev_spec(
const std::string &txrx,
diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h
index 4c5051eaa..549fc9dfa 100644
--- a/host/lib/usrp/x300/x300_fw_common.h
+++ b/host/lib/usrp/x300/x300_fw_common.h
@@ -33,7 +33,7 @@ extern "C" {
#define X300_REVISION_MIN 2
#define X300_FW_COMPAT_MAJOR 4
#define X300_FW_COMPAT_MINOR 0
-#define X300_FPGA_COMPAT_MAJOR 18
+#define X300_FPGA_COMPAT_MAJOR 19
//shared memory sections - in between the stack and the program space
#define X300_FW_SHMEM_BASE 0x6000
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 0483ecf11..37461e2e5 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -809,8 +809,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
////////////////////////////////////////////////////////////////////
_tree->create<time_spec_t>(mb_path / "time" / "now")
.publish(boost::bind(&time_core_3000::get_time_now, mb.radio_perifs[0].time64))
- .subscribe(boost::bind(&time_core_3000::set_time_now, mb.radio_perifs[0].time64, _1))
- .subscribe(boost::bind(&time_core_3000::set_time_now, mb.radio_perifs[1].time64, _1));
+ .subscribe(boost::bind(&x300_impl::sync_times, this, mb, _1))
+ .set(0.0);
_tree->create<time_spec_t>(mb_path / "time" / "pps")
.publish(boost::bind(&time_core_3000::get_time_last_pps, mb.radio_perifs[0].time64))
.subscribe(boost::bind(&time_core_3000::set_time_next_pps, mb.radio_perifs[0].time64, _1))
@@ -1505,6 +1505,14 @@ void x300_impl::update_time_source(mboard_members_t &mb, const std::string &sour
*/
}
+void x300_impl::sync_times(mboard_members_t &mb, const uhd::time_spec_t& t)
+{
+ BOOST_FOREACH(radio_perifs_t &perif, mb.radio_perifs)
+ perif.time64->set_time_sync(t);
+ mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::TIME_SYNC, 1);
+ mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::TIME_SYNC, 0);
+}
+
bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, boost::uint32_t which, double timeout)
{
boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::milliseconds(timeout * 1000.0);
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 521ce8a0e..4de0344bf 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -362,6 +362,7 @@ private:
void set_time_source_out(mboard_members_t&, const bool);
void update_clock_source(mboard_members_t&, const std::string &);
void update_time_source(mboard_members_t&, const std::string &);
+ void sync_times(mboard_members_t&, const uhd::time_spec_t&);
uhd::sensor_value_t get_ref_locked(mboard_members_t& mb);
bool wait_for_clk_locked(mboard_members_t& mb, boost::uint32_t which, double timeout);
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index 489d249ba..de3a3161a 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -213,6 +213,7 @@ namespace uhd { namespace usrp { namespace x300 {
UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN, /*width*/ 1, /*shift*/ 4); //[4]
UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN, /*width*/ 1, /*shift*/ 5); //[5]
UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6); //[6]
+ UHD_DEFINE_SOFT_REG_FIELD(TIME_SYNC, /*width*/ 1, /*shift*/ 7); //[7]
static const boost::uint32_t SRC_EXTERNAL = 0x0;
static const boost::uint32_t SRC_INTERNAL = 0x2;
@@ -225,6 +226,7 @@ namespace uhd { namespace usrp { namespace x300 {
set(PPS_OUT_EN, 0);
set(TCXO_EN, 1);
set(GPSDO_PWR_EN, 1); //GPSDO power always ON
+ set(TIME_SYNC, 0);
}
} clock_ctrl_reg;
diff --git a/host/lib/usrp_clock/octoclock/CMakeLists.txt b/host/lib/usrp_clock/octoclock/CMakeLists.txt
index d3728344e..d2b70e356 100644
--- a/host/lib/usrp_clock/octoclock/CMakeLists.txt
+++ b/host/lib/usrp_clock/octoclock/CMakeLists.txt
@@ -19,10 +19,7 @@
# Conditionally configure the OctoClock support
########################################################################
IF(ENABLE_OCTOCLOCK)
- ADD_DEFINITIONS(-DIHEX_USE_STDBOOL)
-
LIBUHD_APPEND_SOURCES(
- ${CMAKE_CURRENT_SOURCE_DIR}/kk_ihex_read.c
${CMAKE_CURRENT_SOURCE_DIR}/octoclock_eeprom.cpp
${CMAKE_CURRENT_SOURCE_DIR}/octoclock_image_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/octoclock_impl.cpp
diff --git a/host/lib/usrp_clock/octoclock/kk_ihex.h b/host/lib/usrp_clock/octoclock/kk_ihex.h
deleted file mode 100644
index 20eba43cc..000000000
--- a/host/lib/usrp_clock/octoclock/kk_ihex.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * kk_ihex.h: A simple library for reading and writing the Intel HEX
- * or IHEX format. Intended mainly for embedded systems, and thus
- * somewhat optimised for size at the expense of error handling and
- * generality.
- *
- * USAGE
- * -----
- *
- * The library has been split into read and write parts, which use a
- * common data structure (`struct ihex_state`), but each can be used
- * independently. Include the header `kk_ihex_read.h` for reading, and/or
- * the header `kk_ihex_write.h` for writing (and link with their respective
- * object files). Both can be used simultaneously - this header defines
- * the shared data structures and definitions.
- *
- *
- * READING INTEL HEX DATA
- * ----------------------
- *
- * To read data in the Intel HEX format, you must perform the actual reading
- * of bytes using other means (e.g., stdio). The bytes read must then be
- * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions
- * will then call `ihex_data_read`, at which stage the `struct ihex_state`
- * structure will contain the data along with its address. See the header
- * `kk_ihex_read.h` for details and example implementation of `ihex_data_read`.
- *
- * The sequence to read data in IHEX format is:
- * struct ihex_state ihex;
- * ihex_begin_read(&ihex);
- * ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes);
- * ihex_end_read(&ihex);
- *
- *
- * WRITING BINARY DATA AS INTEL HEX
- * --------------------------------
- *
- * In order to write out data, the `ihex_write_at_address` or
- * `ihex_write_at_segment` functions are used to set the data location,
- * and then the binary bytes are written with `ihex_write_byte` and/or
- * `ihex_write_bytes`. The writing functions will then call the function
- * `ihex_flush_buffer` whenever the internal write buffer needs to be
- * cleared - it is up to the caller to provide an implementation of
- * `ihex_flush_buffer` to do the actual writing. See the header
- * `kk_ihex_write.h` for details and an example implementation.
- *
- * See the declaration further down for an example implementation.
- *
- * The sequence to write data in IHEX format is:
- * struct ihex_state ihex;
- * ihex_init(&ihex);
- * ihex_write_at_address(&ihex, 0);
- * ihex_write_bytes(&ihex, my_data, length_of_my_data);
- * ihex_end_write(&ihex);
- *
- * For outputs larger than 64KiB, 32-bit linear addresses are output. Normally
- * the initial linear extended address record of zero is NOT written - it can
- * be forced by setting `ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW` before
- * writing the first byte.
- *
- * Gaps in the data may be created by calling `ihex_write_at_address` with the
- * new starting address without calling `ihex_end_write` in between.
- *
- *
- * The same `struct ihex_state` may be used either for reading or writing,
- * but NOT both at the same time. Furthermore, a global output buffer is
- * used for writing, i.e., multiple threads must not write simultaneously
- * (but multiple writes may be interleaved).
- *
- *
- * CONSERVING MEMORY
- * -----------------
- *
- * For memory-critical use, you can save additional memory by defining
- * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that
- * this limit affects both reading and writing, so the resulting library
- * will be unable to read lines with more than this number of data bytes.
- * That said, I haven't encountered any IHEX files with more than 32
- * data bytes per line. For write only there is no reason to define the
- * maximum as greater than the line length you'll actually be writing,
- * e.g., 32 or 16.
- *
- * If the write functionality is only occasionally used, you can provide
- * your own buffer for the duration by defining `IHEX_EXTERNAL_WRITE_BUFFER`
- * and providing a `char *ihex_write_buffer` which points to valid storage
- * for at least `IHEX_WRITE_BUFFER_LENGTH` characters from before the first
- * call to any IHEX write function to until after the last.
- *
- * If you are doing both reading and writing, you can define the maximum
- * output length separately as `IHEX_MAX_OUTPUT_LINE_LENGTH` - this will
- * decrease the write buffer size, but `struct ihex_state` will still
- * use the larger `IHEX_LINE_MAX_LENGTH` for its data storage.
- *
- * You can also save a few additional bytes by disabling support for
- * segmented addresses, by defining `IHEX_DISABLE_SEGMENTS`. Both the
- * read and write modules need to be build with the same option, as the
- * resulting data structures will not be compatible otherwise. To be honest,
- * this is a fairly pointless optimisation.
- *
- *
- * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/
- * Provided with absolutely no warranty, use at your own risk only.
- * Use and distribute freely, mark modified copies as such.
- */
-
-#ifndef KK_IHEX_H
-#define KK_IHEX_H
-
-#define KK_IHEX_VERSION "2015-08-10"
-
-#include <stdint.h>
-
-#ifdef IHEX_USE_STDBOOL
-#include <stdbool.h>
-typedef bool ihex_bool_t;
-#else
-typedef uint_fast8_t ihex_bool_t;
-#endif
-
-typedef uint_least32_t ihex_address_t;
-typedef uint_least16_t ihex_segment_t;
-typedef int ihex_count_t;
-
-// Maximum number of data bytes per line (applies to both reading and
-// writing!); specify 255 to support reading all possible lengths. Less
-// can be used to limit memory footprint on embedded systems, e.g.,
-// most programs with IHEX output use 32.
-#ifndef IHEX_LINE_MAX_LENGTH
-#define IHEX_LINE_MAX_LENGTH 255
-#endif
-
-enum ihex_flags {
- IHEX_FLAG_ADDRESS_OVERFLOW = 0x80 // 16-bit address overflow
-};
-typedef uint8_t ihex_flags_t;
-
-typedef struct ihex_state {
- ihex_address_t address;
-#ifndef IHEX_DISABLE_SEGMENTS
- ihex_segment_t segment;
-#endif
- ihex_flags_t flags;
- uint8_t line_length;
- uint8_t length;
- uint8_t data[IHEX_LINE_MAX_LENGTH + 1];
-} kk_ihex_t;
-
-enum ihex_record_type {
- IHEX_DATA_RECORD,
- IHEX_END_OF_FILE_RECORD,
- IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD,
- IHEX_START_SEGMENT_ADDRESS_RECORD,
- IHEX_EXTENDED_LINEAR_ADDRESS_RECORD,
- IHEX_START_LINEAR_ADDRESS_RECORD
-};
-typedef uint8_t ihex_record_type_t;
-
-#ifndef IHEX_DISABLE_SEGMENTS
-
-// Resolve segmented address (if any). It is the author's recommendation that
-// segmented addressing not be used (and indeed the write function of this
-// library uses linear 32-bit addressing unless manually overridden).
-//
-#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address + (((ihex_address_t)((ihex)->segment)) << 4))
-//
-// Note that segmented addressing with the above macro is not strictly adherent
-// to the IHEX specification, which mandates that the lowest 16 bits of the
-// address and the index of the data byte must be added modulo 64K (i.e.,
-// at 16 bits precision with wraparound) and the segment address only added
-// afterwards.
-//
-// To implement fully correct segmented addressing, compute the address
-// of _each byte_ with its index in `data` as follows:
-//
-#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((((ihex)->address + (byte_index)) & 0xFFFFU) + (((ihex_address_t)((ihex)->segment)) << 4))
-
-#else // IHEX_DISABLE_SEGMENTS:
-
-#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address)
-#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((ihex)->address + (byte_index))
-
-#endif
-
-// The newline string (appended to every output line, e.g., "\r\n")
-#ifndef IHEX_NEWLINE_STRING
-#define IHEX_NEWLINE_STRING "\n"
-#endif
-
-// See kk_ihex_read.h and kk_ihex_write.h for function declarations!
-
-#endif // !KK_IHEX_H
diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_license.txt b/host/lib/usrp_clock/octoclock/kk_ihex_license.txt
deleted file mode 100644
index 530f413e3..000000000
--- a/host/lib/usrp_clock/octoclock/kk_ihex_license.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013-2015 Kimmo Kulovesi
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_read.c b/host/lib/usrp_clock/octoclock/kk_ihex_read.c
deleted file mode 100644
index 964cdd165..000000000
--- a/host/lib/usrp_clock/octoclock/kk_ihex_read.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * kk_ihex_read.c: A simple library for reading the Intel HEX (IHEX) format.
- *
- * See the header `kk_ihex.h` for instructions.
- *
- * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/
- * Provided with absolutely no warranty, use at your own risk only.
- * Use and distribute freely, mark modified copies as such.
- *
- * Modifications Copyright (c) 2015 National Instruments Corp.
- */
-
-#include "kk_ihex_read.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define IHEX_START ':'
-
-#define AUTODETECT_ADDRESS (~0UL)
-
-#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U)
-
-enum ihex_read_state {
- READ_WAIT_FOR_START = 0,
- READ_COUNT_HIGH = 1,
- READ_COUNT_LOW,
- READ_ADDRESS_MSB_HIGH,
- READ_ADDRESS_MSB_LOW,
- READ_ADDRESS_LSB_HIGH,
- READ_ADDRESS_LSB_LOW,
- READ_RECORD_TYPE_HIGH,
- READ_RECORD_TYPE_LOW,
- READ_DATA_HIGH,
- READ_DATA_LOW
-};
-
-#define IHEX_READ_RECORD_TYPE_MASK 0x07
-#define IHEX_READ_STATE_MASK 0x78
-#define IHEX_READ_STATE_OFFSET 3
-
-void
-ihex_begin_read (struct ihex_state * const ihex) {
- ihex->address = 0;
-#ifndef IHEX_DISABLE_SEGMENTS
- ihex->segment = 0;
-#endif
- ihex->flags = 0;
- ihex->line_length = 0;
- ihex->length = 0;
-}
-
-void
-ihex_read_at_address (struct ihex_state * const ihex, ihex_address_t address) {
- ihex_begin_read(ihex);
- ihex->address = address;
-}
-
-#ifndef IHEX_DISABLE_SEGMENTS
-void
-ihex_read_at_segment (struct ihex_state * const ihex, ihex_segment_t segment) {
- ihex_begin_read(ihex);
- ihex->segment = segment;
-}
-#endif
-
-void
-ihex_end_read (struct ihex_state * const ihex, FILE* outfile) {
- uint_fast8_t type = ihex->flags & IHEX_READ_RECORD_TYPE_MASK;
- uint_fast8_t sum;
- if ((sum = ihex->length) == 0 && type == IHEX_DATA_RECORD) {
- return;
- }
- {
- // compute and validate checksum
- const uint8_t * const eptr = ihex->data + sum;
- const uint8_t *r = ihex->data;
- sum += type + (ihex->address & 0xFFU) + ((ihex->address >> 8) & 0xFFU);
- while (r != eptr) {
- sum += *r++;
- }
- sum = (~sum + 1U) ^ *eptr; // *eptr is the received checksum
- }
- if (ihex_data_read(ihex, type, sum, outfile)) {
- if (type == IHEX_EXTENDED_LINEAR_ADDRESS_RECORD) {
- ihex->address &= 0xFFFFU;
- ihex->address |= (((ihex_address_t) ihex->data[0]) << 24) |
- (((ihex_address_t) ihex->data[1]) << 16);
-#ifndef IHEX_DISABLE_SEGMENTS
- } else if (type == IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD) {
- ihex->segment = (ihex_segment_t) ((ihex->data[0] << 8) | ihex->data[1]);
-#endif
- }
- }
- ihex->length = 0;
- ihex->flags = 0;
-}
-
-void
-ihex_read_byte (struct ihex_state * const ihex, const char byte, FILE* outfile) {
- uint_fast8_t b = (uint_fast8_t) byte;
- uint_fast8_t len = ihex->length;
- uint_fast8_t state = (ihex->flags & IHEX_READ_STATE_MASK);
- ihex->flags ^= state; // turn off the old state
- state >>= IHEX_READ_STATE_OFFSET;
-
- if (b >= '0' && b <= '9') {
- b -= '0';
- } else if (b >= 'A' && b <= 'F') {
- b -= 'A' - 10;
- } else if (b >= 'a' && b <= 'f') {
- b -= 'a' - 10;
- } else if (b == IHEX_START) {
- // sync to a new record at any state
- state = READ_COUNT_HIGH;
- goto end_read;
- } else {
- // ignore unknown characters (e.g., extra whitespace)
- goto save_read_state;
- }
-
- if (!(++state & 1)) {
- // high nybble, store temporarily at end of data:
- b <<= 4;
- ihex->data[len] = b;
- } else {
- // low nybble, combine with stored high nybble:
- b = (ihex->data[len] |= b);
- switch (state >> 1) {
- default:
- // remain in initial state while waiting for :
- return;
- case (READ_COUNT_LOW >> 1):
- // data length
- ihex->line_length = b;
-#if IHEX_LINE_MAX_LENGTH < 255
- if (b > IHEX_LINE_MAX_LENGTH) {
- ihex_end_read(ihex);
- return;
- }
-#endif
- break;
- case (READ_ADDRESS_MSB_LOW >> 1):
- // high byte of 16-bit address
- ihex->address &= ADDRESS_HIGH_MASK; // clear the 16-bit address
- ihex->address |= ((ihex_address_t) b) << 8U;
- break;
- case (READ_ADDRESS_LSB_LOW >> 1):
- // low byte of 16-bit address
- ihex->address |= (ihex_address_t) b;
- break;
- case (READ_RECORD_TYPE_LOW >> 1):
- // record type
- if (b & ~IHEX_READ_RECORD_TYPE_MASK) {
- // skip unknown record types silently
- return;
- }
- ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK) | b;
- break;
- case (READ_DATA_LOW >> 1):
- if (len < ihex->line_length) {
- // data byte
- ihex->length = len + 1;
- state = READ_DATA_HIGH;
- goto save_read_state;
- }
- // end of line (last "data" byte is checksum)
- state = READ_WAIT_FOR_START;
- end_read:
- ihex_end_read(ihex, outfile);
- }
- }
-save_read_state:
- ihex->flags |= state << IHEX_READ_STATE_OFFSET;
-}
-
-void
-ihex_read_bytes (struct ihex_state * ihex,
- const char * data,
- ihex_count_t count,
- FILE* outfile) {
- while (count > 0) {
- ihex_read_byte(ihex, *data++, outfile);
- --count;
- }
-}
-
-ihex_bool_t
-ihex_data_read (struct ihex_state *ihex,
- ihex_record_type_t type,
- ihex_bool_t error,
- FILE* outfile) {
- unsigned long line_number = 1L;
- unsigned long file_position = 0L;
- unsigned long address_offset = 0L;
- bool debug_enabled = false;
-
- if (error) {
- (void) fprintf(stderr, "Checksum error on line %lu\n", line_number);
- return false;
- }
- if ((error = (ihex->length < ihex->line_length))) {
- (void) fprintf(stderr, "Line length error on line %lu\n", line_number);
- return false;
- }
- if (!outfile) {
- (void) fprintf(stderr, "Excess data after end of file record\n");
- return false;
- }
- if (type == IHEX_DATA_RECORD) {
- unsigned long address = (unsigned long) IHEX_LINEAR_ADDRESS(ihex);
- if (address < address_offset) {
- if (address_offset == AUTODETECT_ADDRESS) {
- // autodetect initial address
- address_offset = address;
- if (debug_enabled) {
- (void) fprintf(stderr, "Address offset: 0x%lx\n",
- address_offset);
- }
- } else {
- (void) fprintf(stderr, "Address underflow on line %lu\n",
- line_number);
- return false;
- }
- }
- address -= address_offset;
- if (address != file_position) {
- if (debug_enabled) {
- (void) fprintf(stderr,
- "Seeking from 0x%lx to 0x%lx on line %lu\n",
- file_position, address, line_number);
- }
- if (outfile == stdout || fseek(outfile, (long) address, SEEK_SET)) {
- if (file_position < address) {
- // "seek" forward in stdout by writing NUL bytes
- do {
- (void) fputc('\0', outfile);
- } while (++file_position < address);
- } else {
- perror("fseek");
- return false;
- }
- }
- file_position = address;
- }
- if (!fwrite(ihex->data, ihex->length, 1, outfile)) {
- perror("fwrite");
- return false;
- }
- file_position += ihex->length;
- } else if (type == IHEX_END_OF_FILE_RECORD) {
- if (debug_enabled) {
- (void) fprintf(stderr, "%lu bytes written\n", file_position);
- }
- if (outfile != stdout) {
- (void) fclose(outfile);
- }
- outfile = NULL;
- }
- return true;
-}
diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_read.h b/host/lib/usrp_clock/octoclock/kk_ihex_read.h
deleted file mode 100644
index 303622b18..000000000
--- a/host/lib/usrp_clock/octoclock/kk_ihex_read.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * kk_ihex_read.h: A simple library for reading Intel HEX data. See
- * the accompanying kk_ihex_write.h for IHEX write support.
- *
- *
- * READING INTEL HEX DATA
- * ----------------------
- *
- * To read data in the Intel HEX format, you must perform the actual reading
- * of bytes using other means (e.g., stdio). The bytes read must then be
- * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions
- * will then call `ihex_data_read`, at which stage the `struct ihex_state`
- * structure will contain the data along with its address. See below for
- * details and example implementation of `ihex_data_read`.
- *
- * The sequence to read data in IHEX format is:
- * struct ihex_state ihex;
- * ihex_begin_read(&ihex);
- * ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes);
- * ihex_end_read(&ihex);
- *
- *
- * CONSERVING MEMORY
- * -----------------
- *
- * For memory-critical use, you can save additional memory by defining
- * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that
- * this limit affects both reading and writing, so the resulting library
- * will be unable to read lines with more than this number of data bytes.
- * That said, I haven't encountered any IHEX files with more than 32
- * data bytes per line.
- *
- *
- * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/
- * Provided with absolutely no warranty, use at your own risk only.
- * Use and distribute freely, mark modified copies as such.
- *
- * Modifications Copyright (c) 2015 National Instruments Corp.
- */
-
-#ifndef KK_IHEX_READ_H
-#define KK_IHEX_READ_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "kk_ihex.h"
-
-#include <stdio.h>
-
-// Begin reading at address 0
-void ihex_begin_read(struct ihex_state * const ihex);
-
-// Begin reading at `address` (the lowest 16 bits of which will be ignored);
-// this is required only if the high bytes of the 32-bit starting address
-// are not specified in the input data and they are non-zero
-void ihex_read_at_address(struct ihex_state * const ihex,
- ihex_address_t address);
-
-// Read a single character
-void ihex_read_byte(struct ihex_state * const ihex, const char byte, FILE* outfile);
-
-// Read `count` bytes from `data`
-void ihex_read_bytes(struct ihex_state * ihex,
- const char * data,
- ihex_count_t count,
- FILE* outfile);
-
-// End reading (may call `ihex_data_read` if there is data waiting)
-void ihex_end_read(struct ihex_state * const ihex, FILE* outfile);
-
-// Called when a complete line has been read, the record type of which is
-// passed as `type`. The `ihex` structure will have its fields `data`,
-// `line_length`, `address`, and `segment` set appropriately. In case
-// of reading an `IHEX_EXTENDED_LINEAR_ADDRESS_RECORD` or an
-// `IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD` the record's data is not
-// yet parsed - it will be parsed into the `address` or `segment` field
-// only if `ihex_data_read` returns `true`. This allows manual handling
-// of extended addresses by parsing the `ihex->data` bytes.
-//
-// Possible error cases include checksum mismatch (which is indicated
-// as an argument), and excessive line length (in case this has been
-// compiled with `IHEX_LINE_MAX_LENGTH` less than 255) which is indicated
-// by `line_length` greater than `length`. Unknown record types and
-// other erroneous data is usually silently ignored by this minimalistic
-// parser. (It is recommended to compute a hash over the complete data
-// once received and verify that against the source.)
-//
-// Example implementation:
-//
-// ihex_bool_t ihex_data_read(struct ihex_state *ihex,
-// ihex_record_type_t type,
-// ihex_bool_t error) {
-// error = error || (ihex->length < ihex->line_length);
-// if (type == IHEX_DATA_RECORD && !error) {
-// (void) fseek(outfile, IHEX_LINEAR_ADDRESS(ihex), SEEK_SET);
-// (void) fwrite(ihex->data, 1, ihex->length, outfile);
-// } else if (type == IHEX_END_OF_FILE_RECORD) {
-// (void) fclose(outfile);
-// }
-// return !error;
-// }
-//
-ihex_bool_t ihex_data_read(struct ihex_state *ihex,
- ihex_record_type_t type,
- ihex_bool_t checksum_mismatch,
- FILE* outfile);
-
-// Begin reading at `segment`; this is required only if the initial segment
-// is not specified in the input data and it is non-zero.
-//
-#ifndef IHEX_DISABLE_SEGMENTS
-void ihex_read_at_segment(struct ihex_state *ihex, ihex_segment_t segment);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif // !KK_IHEX_READ_H
diff --git a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
index 8b47da7e5..fdb254024 100644
--- a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
+++ b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
@@ -17,8 +17,8 @@
#include "octoclock_impl.hpp"
#include "common.h"
-#include "kk_ihex_read.h"
+#include "../../utils/ihex.hpp"
#include <uhd/device.hpp>
#include <uhd/image_loader.hpp>
#include <uhd/transport/udp_simple.hpp>
@@ -34,6 +34,8 @@
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
+#include <algorithm>
+#include <iterator>
#include <cstdio>
#include <cstring>
#include <fstream>
@@ -54,83 +56,70 @@ using namespace uhd::transport;
typedef struct {
bool found;
uhd::device_addr_t dev_addr;
- std::string given_filepath;
- std::string actual_filepath; // If using a .hex, this is the converted .bin
- bool from_hex;
- boost::uint32_t size;
+ std::string image_filepath;
boost::uint16_t crc;
boost::uint16_t num_blocks;
udp_simple::sptr ctrl_xport;
udp_simple::sptr fw_xport;
boost::uint8_t data_in[udp_simple::mtu];
+ std::vector<boost::uint8_t> image;
} octoclock_session_t;
static void octoclock_calculate_crc(octoclock_session_t &session){
- std::ifstream ifile(session.actual_filepath.c_str());
- boost::uint8_t temp_image[OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES];
- ifile.read((char*)temp_image, session.size);
-
session.crc = 0xFFFF;
- for(size_t i = 0; i < session.size; i++){
- session.crc ^= temp_image[i];
+ for(size_t i = 0; i < session.image.size(); i++)
+ {
+ session.crc ^= session.image[i];
for(boost::uint8_t j = 0; j < 8; ++j){
if(session.crc & 1) session.crc = (session.crc >> 1) ^ 0xA001;
else session.crc = (session.crc >> 1);
}
}
-
- ifile.close();
}
-static void octoclock_convert_ihex(octoclock_session_t &session){
- struct ihex_state ihex;
- ihex_count_t count;
- char buf[256];
- FILE* infile = fopen(session.given_filepath.c_str(), "r");
- FILE* outfile = fopen(session.actual_filepath.c_str(), "w");
- uint64_t line_number = 1;
-
- ihex_begin_read(&ihex);
- while(fgets(buf, 256, infile)){
- count = ihex_count_t(strlen(buf));
- ihex_read_bytes(&ihex, buf, count, outfile);
- line_number += (count && buf[count - 1] == '\n');
+static void octoclock_read_bin(octoclock_session_t &session)
+{
+ std::ifstream bin_file(session.image_filepath.c_str(), std::ios::in | std::ios::binary);
+ if (not bin_file.is_open()) {
+ throw uhd::io_error("Could not read image file.");
}
- ihex_end_read(&ihex, outfile); // Closes outfile
- (void)fclose(infile);
+ size_t filesize = fs::file_size(session.image_filepath);
+ session.image.clear();
+ session.image.resize(filesize);
+ bin_file.read((char*)&session.image[0], filesize);
+ if(size_t(bin_file.gcount()) != filesize) {
+ throw uhd::io_error("Failed to read firmware image.");
+ }
+
+ bin_file.close();
}
static void octoclock_validate_firmware_image(octoclock_session_t &session){
- if(not fs::exists(session.given_filepath)){
+ if(not fs::exists(session.image_filepath)){
throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\"")
- % session.given_filepath));
+ % session.image_filepath));
}
- std::string extension = fs::extension(session.given_filepath);
+ std::string extension = fs::extension(session.image_filepath);
if(extension == ".bin"){
- session.actual_filepath = session.given_filepath;
- session.from_hex = false;
+ octoclock_read_bin(session);
}
else if(extension == ".hex"){
- session.actual_filepath = fs::path(fs::path(uhd::get_tmp_path()) /
- str(boost::format("octoclock_fw_%d.bin")
- % time_spec_t::get_system_time().get_full_secs())
- ).string();
-
- octoclock_convert_ihex(session);
- session.from_hex = true;
+ ihex_reader hex_reader(session.image_filepath);
+ session.image = hex_reader.to_vector(OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES);
}
- else throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .hex or .bin.")));
+ else throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .hex or .bin.")
+ % extension));
- session.size = fs::file_size(session.actual_filepath);
- if(session.size > OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES){
+ if(session.image.size() > OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES){
throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d")
- % session.size % OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES));
+ % session.image.size() % OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES));
}
- session.num_blocks = (session.size % OCTOCLOCK_BLOCK_SIZE) ? ((session.size / OCTOCLOCK_BLOCK_SIZE) + 1)
- : (session.size / OCTOCLOCK_BLOCK_SIZE);
+ session.num_blocks = (session.image.size() % OCTOCLOCK_BLOCK_SIZE)
+ ? ((session.image.size() / OCTOCLOCK_BLOCK_SIZE) + 1)
+ : (session.image.size() / OCTOCLOCK_BLOCK_SIZE);
octoclock_calculate_crc(session);
}
@@ -164,14 +153,15 @@ static void octoclock_setup_session(octoclock_session_t &session,
}
session.dev_addr = devs[0];
+ session.found = true;
// If no filepath is given, use the default
if(filepath == ""){
- session.given_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex")
+ session.image_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex")
% session.dev_addr.get("revision","4")
));
}
- else session.given_filepath = filepath;
+ else session.image_filepath = filepath;
octoclock_validate_firmware_image(session);
@@ -231,10 +221,10 @@ static void octoclock_burn(octoclock_session_t &session){
const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
// Tell OctoClock to prepare for burn
- pkt_out.len = htonx<boost::uint16_t>(session.size);
+ pkt_out.len = htonx<boost::uint16_t>(session.image.size());
size_t len = 0;
std::cout << " -- Preparing OctoClock for firmware load..." << std::flush;
- pkt_out.len = session.size;
+ pkt_out.len = session.image.size();
pkt_out.crc = session.crc;
UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, PREPARE_FW_BURN_CMD, pkt_out, len, session.data_in);
if(UHD_OCTOCLOCK_PACKET_MATCHES(FW_BURN_READY_ACK, pkt_out, pkt_in, len)){
@@ -242,14 +232,10 @@ static void octoclock_burn(octoclock_session_t &session){
}
else{
std::cout << "failed." << std::endl;
- if(session.from_hex){
- fs::remove(session.actual_filepath);
- }
throw uhd::runtime_error("Failed to prepare OctoClock for firmware load.");
}
// Start burning
- std::ifstream image(session.actual_filepath.c_str(), std::ios::binary);
for(size_t i = 0; i < session.num_blocks; i++){
pkt_out.sequence++;
pkt_out.addr = i * OCTOCLOCK_BLOCK_SIZE;
@@ -260,14 +246,10 @@ static void octoclock_burn(octoclock_session_t &session){
<< std::flush;
memset(pkt_out.data, 0, OCTOCLOCK_BLOCK_SIZE);
- image.read((char*)pkt_out.data, OCTOCLOCK_BLOCK_SIZE);
+ memcpy((char*)pkt_out.data, &session.image[pkt_out.addr], OCTOCLOCK_BLOCK_SIZE);
UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, FILE_TRANSFER_CMD, pkt_out, len, session.data_in);
if(not UHD_OCTOCLOCK_PACKET_MATCHES(FILE_TRANSFER_ACK, pkt_out, pkt_in, len)){
- image.close();
std::cout << std::endl;
- if(session.from_hex){
- fs::remove(session.actual_filepath);
- }
throw uhd::runtime_error("Failed to load firmware.");
}
}
@@ -275,7 +257,6 @@ static void octoclock_burn(octoclock_session_t &session){
std::cout << str(boost::format("\r -- Loading firmware: 100%% (%d/%d blocks)")
% session.num_blocks % session.num_blocks)
<< std::endl;
- image.close();
}
static void octoclock_verify(octoclock_session_t &session){
@@ -285,7 +266,6 @@ static void octoclock_verify(octoclock_session_t &session){
const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
size_t len = 0;
- std::ifstream image(session.actual_filepath.c_str(), std::ios::binary);
boost::uint8_t image_part[OCTOCLOCK_BLOCK_SIZE];
boost::uint16_t cmp_len = 0;
for(size_t i = 0; i < session.num_blocks; i++){
@@ -298,34 +278,22 @@ static void octoclock_verify(octoclock_session_t &session){
<< std::flush;
memset(image_part, 0, OCTOCLOCK_BLOCK_SIZE);
- image.read((char*)image_part, OCTOCLOCK_BLOCK_SIZE);
- cmp_len = image.gcount();
+ memcpy((char*)image_part, &session.image[pkt_out.addr], OCTOCLOCK_BLOCK_SIZE);
+ cmp_len = std::min<size_t>(OCTOCLOCK_BLOCK_SIZE, session.image.size() - size_t(pkt_out.addr));
UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, READ_FW_CMD, pkt_out, len, session.data_in);
if(UHD_OCTOCLOCK_PACKET_MATCHES(READ_FW_ACK, pkt_out, pkt_in, len)){
if(memcmp(pkt_in->data, image_part, cmp_len)){
std::cout << std::endl;
- image.close();
- if(session.from_hex){
- fs::remove(session.actual_filepath);
- }
throw uhd::runtime_error("Failed to verify OctoClock firmware.");
}
}
else{
std::cout << std::endl;
- image.close();
- if(session.from_hex){
- fs::remove(session.actual_filepath);
- }
throw uhd::runtime_error("Failed to verify OctoClock firmware.");
}
}
- image.close();
- if(session.from_hex){
- fs::remove(session.actual_filepath);
- }
std::cout << str(boost::format("\r -- Verifying firmware load: 100%% (%d/%d blocks)")
% session.num_blocks % session.num_blocks)
<< std::endl;
@@ -360,7 +328,7 @@ bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loade
std::cout << boost::format("Unit: OctoClock (%s)")
% session.dev_addr["addr"]
<< std::endl;
- std::cout << "Firmware: " << session.given_filepath << std::endl;
+ std::cout << "Firmware: " << session.image_filepath << std::endl;
octoclock_burn(session);
octoclock_verify(session);
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
index c5c975dfa..72e2f3f50 100644
--- a/host/lib/utils/CMakeLists.txt
+++ b/host/lib/utils/CMakeLists.txt
@@ -132,6 +132,7 @@ SET_SOURCE_FILES_PROPERTIES(
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/csv.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/ihex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp
${CMAKE_CURRENT_SOURCE_DIR}/log.cpp
${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp
diff --git a/host/lib/utils/ihex.cpp b/host/lib/utils/ihex.cpp
new file mode 100644
index 000000000..a29ac3e72
--- /dev/null
+++ b/host/lib/utils/ihex.cpp
@@ -0,0 +1,236 @@
+//
+// Copyright 2015 Ettus Research LLC
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#include "ihex.hpp"
+#include <uhd/exception.hpp>
+#include <boost/format.hpp>
+#include <boost/make_shared.hpp>
+#include <sstream>
+#include <fstream>
+
+using namespace uhd;
+
+/*!
+ * Verify checksum of a Intel HEX record
+ * \param record a line from an Intel HEX file
+ * \return true if record is valid, false otherwise
+ */
+static bool checksum(const std::string& record)
+{
+ size_t len = record.length();
+ unsigned char sum = 0;
+ unsigned int val;
+
+ for (size_t i = 1; i < len; i += 2) {
+ std::istringstream(record.substr(i, 2)) >> std::hex >> val;
+ sum += val;
+ }
+
+ if (sum == 0)
+ return true;
+ else
+ return false;
+}
+
+
+/*!
+ * 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
+ */
+static bool parse_record(
+ const std::string& record,
+ boost::uint16_t &len,
+ boost::uint16_t &addr,
+ boost::uint16_t &type,
+ unsigned char* data
+) {
+ unsigned int i;
+ 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;
+
+ if (len > (2 * (record.length() - 9))) // sanity check to prevent buffer overrun
+ return false;
+
+ for (i = 0; i < len; i++) {
+ std::istringstream(record.substr(9 + 2 * i, 2)) >> std::hex >> val;
+ data[i] = (unsigned char) val;
+ }
+
+ return true;
+}
+
+
+ihex_reader::ihex_reader(const std::string &ihex_filename)
+ : _ihex_filename(ihex_filename)
+{
+ // nop
+}
+
+
+void ihex_reader::read(ihex_reader::record_handle_type record_handler)
+{
+ const char *filename = _ihex_filename.c_str();
+
+ /* Fields used in every record. */
+ boost::uint16_t len = 0;
+ boost::uint16_t type = 0;
+ boost::uint16_t lower_address_bits = 0x0000;
+ static const int MAX_RECORD_LENGTH = 255;
+ unsigned char data[MAX_RECORD_LENGTH];
+
+ /* Can be set by the Intel HEX record 0x04, used for all 0x00 records
+ * thereafter. Note this field takes the place of the 'index' parameter in
+ * libusb calls, and is necessary for FX3's 32-bit addressing. */
+ boost::uint16_t upper_address_bits = 0x0000;
+
+ std::ifstream file;
+ file.open(filename, std::ifstream::in);
+
+ if(!file.good()) {
+ throw uhd::io_error("ihex_reader::read(): cannot open firmware input file");
+ }
+
+ while (!file.eof()) {
+ boost::int32_t ret = 0;
+ std::string record;
+ file >> record;
+
+ if (!(record.length() > 0))
+ continue;
+
+ /* Check for valid Intel HEX record. */
+ if (!checksum(record)
+ || !parse_record(record, len, lower_address_bits, type, data)) {
+ throw uhd::io_error("ihex_reader::read(): bad intel hex record checksum");
+ }
+
+ /* Type 0x00: Data. */
+ if (type == 0x00) {
+ ret = record_handler(lower_address_bits, upper_address_bits, data, len);
+
+ if (ret < 0) {
+ throw uhd::io_error("ihex_reader::read(): record hander returned failure code");
+ }
+ }
+
+ /* Type 0x01: EOF. */
+ else if (type == 0x01) {
+ if (lower_address_bits != 0x0000 || len != 0 ) {
+ throw uhd::io_error("ihex_reader::read(): For EOF record, address must be 0, length must be 0.");
+ }
+
+ /* Successful termination! */
+ file.close();
+ return;
+ }
+
+ /* Type 0x04: Extended Linear Address Record. */
+ else if (type == 0x04) {
+ if (lower_address_bits != 0x0000 || len != 2 ) {
+ throw uhd::io_error("ihex_reader::read(): For ELA record, address must be 0, length must be 2.");
+ }
+
+ upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\
+ + ((boost::uint16_t)(data[1] & 0x00FF));
+ }
+
+ /* Type 0x05: Start Linear Address Record. */
+ else if (type == 0x05) {
+ if (lower_address_bits != 0x0000 || len != 4 ) {
+ throw uhd::io_error("ihex_reader::read(): For SLA record, address must be 0, length must be 4.");
+ }
+
+ /* The firmware load is complete. We now need to tell the CPU
+ * to jump to an execution address start point, now contained within
+ * the data field. Parse these address bits out, and then push the
+ * instruction. */
+ upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\
+ + ((boost::uint16_t)(data[1] & 0x00FF));
+ lower_address_bits = ((boost::uint16_t)((data[2] & 0x00FF) << 8))\
+ + ((boost::uint16_t)(data[3] & 0x00FF));
+
+ record_handler(lower_address_bits, upper_address_bits, 0, 0);
+ }
+
+ /* If we receive an unknown record type, error out. */
+ else {
+ throw uhd::io_error(str(boost::format("ihex_reader::read(): unsupported record type: %X.") % type));
+ }
+ }
+
+ /* There was no valid EOF. */
+ throw uhd::io_error("ihex_reader::read(): No EOF record found.");
+}
+
+// We need a functor for the cast, a lambda would be perfect...
+int _file_writer_callback(
+ boost::shared_ptr<std::ofstream> output_file,
+ unsigned char *buff,
+ boost::uint16_t len
+) {
+ output_file->write((const char *) buff, len);
+ return 0;
+}
+
+void ihex_reader::to_bin_file(const std::string &bin_filename)
+{
+ boost::shared_ptr<std::ofstream> output_file(boost::make_shared<std::ofstream>());
+ output_file->open(bin_filename.c_str(), std::ios::out | std::ios::binary);
+ if (not output_file->is_open()) {
+ throw uhd::io_error(str(boost::format("Could not open file for writing: %s") % bin_filename));
+ }
+
+ this->read(boost::bind(&_file_writer_callback, output_file, _3, _4));
+
+ output_file->close();
+}
+
+// We need a functor for the cast, a lambda would be perfect...
+int _vector_writer_callback(
+ std::vector<boost::uint8_t>& vector,
+ unsigned char *buff,
+ boost::uint16_t len
+) {
+ for (size_t i = 0; i < len; i++) {
+ vector.push_back(buff[i]);
+ }
+ return 0;
+}
+
+#define DEFAULT_SIZE_ESTIMATE 8000000
+std::vector<boost::uint8_t> ihex_reader::to_vector(const size_t size_estimate)
+{
+ std::vector<boost::uint8_t> buf;
+ buf.reserve(size_estimate == 0 ? DEFAULT_SIZE_ESTIMATE : size_estimate);
+
+ this->read(boost::bind(&_vector_writer_callback, boost::ref(buf), _3, _4));
+
+ return buf;
+}
+
diff --git a/host/lib/utils/ihex.hpp b/host/lib/utils/ihex.hpp
new file mode 100644
index 000000000..9df1fcbc3
--- /dev/null
+++ b/host/lib/utils/ihex.hpp
@@ -0,0 +1,79 @@
+//
+// Copyright 2015 Ettus Research LLC
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_IHEX_READER_HPP
+#define INCLUDED_IHEX_READER_HPP
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/cstdint.hpp>
+#include <string>
+#include <vector>
+
+namespace uhd {
+
+class ihex_reader
+{
+public:
+ // Arguments are: lower address bits, upper address bits, buff, length
+ typedef boost::function<int(boost::uint16_t,boost::uint16_t,unsigned char*,boost::uint16_t)> record_handle_type;
+
+ /*
+ * \param ihex_filename Path to the *.ihx file
+ */
+ ihex_reader(const std::string &ihex_filename);
+
+ /*! Read an Intel HEX file and handle it record by record.
+ *
+ * Every record is individually passed off to a record handler function.
+ *
+ * \param record_handler The functor that will handle the records.
+ *
+ * \throws uhd::io_error if the HEX file is corrupted or unreadable.
+ */
+ void read(record_handle_type record_handler);
+
+ /* Convert the ihex file to a bin file.
+ *
+ * *Note:* This function makes the assumption that the hex file is
+ * contiguous, and starts at address zero.
+ *
+ * \param bin_filename Output filename.
+ *
+ * \throws uhd::io_error if the HEX file is corrupted or unreadable.
+ */
+ void to_bin_file(const std::string &bin_filename);
+
+ /*! Copy the ihex file into a buffer.
+ *
+ * Very similar functionality as to_bin_file().
+ *
+ * *Note:* This function makes the assumption that the hex file is
+ * contiguous, and starts at address zero.
+ *
+ * \throws uhd::io_error if the HEX file is corrupted or unreadable.
+ */
+ std::vector<boost::uint8_t> to_vector(const size_t size_estimate = 0);
+
+private:
+ const std::string _ihex_filename;
+};
+
+}; /* namespace uhd */
+
+#endif /* INCLUDED_IHEX_READER_HPP */
+
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index 1ea86f2cc..9ab95596d 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -91,10 +91,9 @@ IF(ENABLE_OCTOCLOCK)
SET(octoclock_burner_sources
octoclock_firmware_burner.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp_clock/octoclock/kk_ihex_read.c
+ ${CMAKE_SOURCE_DIR}/lib/utils/ihex.cpp
)
- ADD_DEFINITIONS(-DIHEX_USE_STDBOOL)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/usrp_clock/octoclock)
ADD_EXECUTABLE(octoclock_firmware_burner ${octoclock_burner_sources})
TARGET_LINK_LIBRARIES(octoclock_firmware_burner uhd ${Boost_LIBRARIES})
diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp
index a3eaf862a..a6896c868 100644
--- a/host/utils/b2xx_fx3_utils.cpp
+++ b/host/utils/b2xx_fx3_utils.cpp
@@ -52,7 +52,8 @@ const static vid_pid_t known_vid_pids[] = {
{FX3_VID, FX3_DEFAULT_PID},
{FX3_VID, FX3_REENUM_PID},
{B200_VENDOR_ID, B200_PRODUCT_ID},
- {B200_VENDOR_ID, B205_PRODUCT_ID},
+ {B200_VENDOR_ID, B200MINI_PRODUCT_ID},
+ {B200_VENDOR_ID, B205MINI_PRODUCT_ID},
{B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID},
{B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID}
};
@@ -175,7 +176,7 @@ uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, c
vp = known_vid_pid_vector[i];
handles = uhd::transport::usb_device_handle::get_device_list(vp.vid, vp.pid);
}
-
+
}
if (handles.size() > 0)
diff --git a/host/utils/octoclock_firmware_burner.cpp b/host/utils/octoclock_firmware_burner.cpp
index c338cd818..326985df5 100644
--- a/host/utils/octoclock_firmware_burner.cpp
+++ b/host/utils/octoclock_firmware_burner.cpp
@@ -42,7 +42,7 @@
#include <uhd/utils/safe_main.hpp>
#include "../lib/usrp_clock/octoclock/common.h"
-#include "kk_ihex_read.h"
+#include "../lib/utils/ihex.hpp"
#define MAX_FIRMWARE_SIZE 1024*120
#define BLOCK_SIZE 256
@@ -142,7 +142,7 @@ device_addrs_t bootloader_find(const std::string &ip_addr){
device_addrs_t addrs;
boost::system_time comm_timeout = boost::get_system_time() + boost::posix_time::milliseconds(3000);
-
+
while(boost::get_system_time() < comm_timeout){
UHD_OCTOCLOCK_SEND_AND_RECV(udp_transport, OCTOCLOCK_QUERY_CMD, pkt_out, len, octoclock_data);
if(UHD_OCTOCLOCK_PACKET_MATCHES(OCTOCLOCK_QUERY_ACK, pkt_out, pkt_in, len) and
@@ -292,22 +292,8 @@ void finalize(udp_simple::sptr udp_transport){
}
void octoclock_convert_ihex(const std::string &hex_path, const std::string &bin_path){
- struct ihex_state ihex;
- ihex_count_t count;
- char buf[256];
- FILE* infile = fopen(hex_path.c_str(), "r");
- FILE* outfile = fopen(bin_path.c_str(), "w");
- uint64_t line_number = 1;
-
- ihex_begin_read(&ihex);
- while(fgets(buf, 256, infile)){
- count = ihex_count_t(strlen(buf));
- ihex_read_bytes(&ihex, buf, count, outfile);
- line_number += (count && buf[count - 1] == '\n');
- }
- ihex_end_read(&ihex, outfile); // Closes outfile
-
- (void)fclose(infile);
+ ihex_reader hex_reader(hex_path);
+ hex_reader.to_bin_file(bin_path);
}
int UHD_SAFE_MAIN(UHD_UNUSED(int argc), UHD_UNUSED(char *argv[])){
diff --git a/host/utils/uhd-usrp.rules b/host/utils/uhd-usrp.rules
index e10c86f13..76bccfefa 100644
--- a/host/utils/uhd-usrp.rules
+++ b/host/utils/uhd-usrp.rules
@@ -24,5 +24,6 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0002", MODE:="066
#B200
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0020", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0021", MODE:="0666"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0022", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="3923", ATTRS{idProduct}=="7813", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="3923", ATTRS{idProduct}=="7814", MODE:="0666"