aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG23
-rw-r--r--firmware/usrp3/x300/x300_defs.h2
-rw-r--r--firmware/usrp3/x300/x300_init.c44
-rw-r--r--firmware/usrp3/x300/x300_init.h5
-rw-r--r--firmware/usrp3/x300/x300_main.c47
-rw-r--r--host/CMakeLists.txt7
-rw-r--r--host/docs/vrt_chdr.dox15
-rw-r--r--host/include/uhd/rfnoc/blocks/ddc.xml2
-rw-r--r--host/include/uhd/transport/chdr.hpp6
-rw-r--r--host/include/uhd/transport/vrt_if_packet.hpp2
-rw-r--r--host/lib/experts/expert_container.cpp6
-rw-r--r--host/lib/rfnoc/block_ctrl_base.cpp1
-rw-r--r--host/lib/rfnoc/nocscript/function_table.cpp2
-rw-r--r--host/lib/rfnoc/xports.hpp1
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.cpp4
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.h18
-rw-r--r--host/lib/usrp/cores/rx_frontend_core_3000.cpp1
-rw-r--r--host/lib/usrp/dboard/twinrx/twinrx_gain_tables.cpp1
-rw-r--r--host/lib/usrp/device3/device3_io_impl.cpp2
-rw-r--r--host/lib/usrp/e300/e300_global_regs.hpp1
-rw-r--r--host/lib/usrp/e300/e300_i2c.hpp1
-rw-r--r--host/lib/usrp/e300/e300_impl.hpp3
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp72
-rw-r--r--host/lib/usrp/n230/n230_resource_manager.cpp3
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp2
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp2
-rw-r--r--host/lib/usrp/usrp2/n200_image_loader.cpp2
-rw-r--r--host/lib/usrp/x300/CMakeLists.txt1
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h29
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp95
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp9
-rw-r--r--host/lib/usrp/x300/x300_mb_eeprom.cpp190
-rw-r--r--host/lib/usrp/x300/x300_mb_eeprom.hpp37
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp3
-rw-r--r--host/tests/convert_test.cpp6
-rw-r--r--host/utils/converter_benchmark.cpp4
36 files changed, 491 insertions, 158 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 95eff463c..69aae6a91 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,29 @@
Change Log for Releases
==============================
+
+## 003.010.001.001
+
+- Docs: The protocol for Gen-3 devices is now consistently referred to as CHDR.
+- X300: Fixed EEPROM corruption bug (happened when two processes would access
+ find routines on the same device at the same time). Improved initialization
+ time. CE clock is now 214 MHz. Fixed channel list generation. Find routines
+ now more lenient in case one devices fails (others can still be found then).
+ Improve PCIe behaviour. Fix timed commands for non-TwinRX dboards. Improve
+ AXI Interconnect (faster, improved build timing).
+- N230: Use second_addr (like X300).
+- C API: Added UHD_VERSION macro. Fixed online rate change.
+- Utils: Minor fixes to uhd_images_downloader.
+- Build/CMake: Fixed some Py3k build issues. Fixed many compiler warnings. Allow
+ to specify package names.
+- RFNoC: Fixed sampling rate mismatch error. Noc-Shell uses a non-cascaded 2-clk
+ FIFO. Increase default FIFO sizes on DUC and DDC blocks.
+- UBX: Force on RX driver to eliminate transient.
+- Transport code: Fixed memory leak.
+- FPGA repository: Merged usrp3_rfnoc and usrp3 directories again. Cleaned up
+ superfluous files. Clean separation between Gen-3 and other devices in usrp3.
+
+
## 003.010.001.000
- Fixed multiple compiler warnings
diff --git a/firmware/usrp3/x300/x300_defs.h b/firmware/usrp3/x300/x300_defs.h
index e9e9f34fa..ed756d6fd 100644
--- a/firmware/usrp3/x300/x300_defs.h
+++ b/firmware/usrp3/x300/x300_defs.h
@@ -9,7 +9,7 @@
#define PKT_RAM0_BASE 0x8000
#define SFP0_MAC_BASE 0xC000
#define SFP1_MAC_BASE 0xD000
-#define BOOT_LDR_BASE 0xFC00
+#define BOOT_LDR_BASE 0xFA00
#define UART0_BASE 0xfd00
#define UART0_BAUD 115200
#define UART1_BASE 0xf900
diff --git a/firmware/usrp3/x300/x300_init.c b/firmware/usrp3/x300/x300_init.c
index 57c1faa2c..61d4f4190 100644
--- a/firmware/usrp3/x300/x300_init.c
+++ b/firmware/usrp3/x300/x300_init.c
@@ -1,5 +1,4 @@
#include "x300_init.h"
-#include "x300_defs.h"
#include "ethernet.h"
#include "cron.h"
#include <wb_utils.h>
@@ -17,27 +16,7 @@
static wb_pkt_iface64_config_t pkt_config;
-struct x300_eeprom_map
-{
- //indentifying numbers
- unsigned char revision[2];
- unsigned char product[2];
- uint8_t _pad0[4];
-
- //all the mac addrs
- uint8_t mac_addr0[6];
- uint8_t _pad1[2];
- uint8_t mac_addr1[6];
- uint8_t _pad2[2];
-
- //all the IP addrs
- uint32_t gateway;
- uint32_t subnet[4];
- uint32_t ip_addr[4];
- uint8_t _pad3[16];
-};
-
-static struct x300_eeprom_map default_map = {
+static x300_eeprom_map_t default_map = {
.mac_addr0 = X300_DEFAULT_MAC_ADDR_0,
.mac_addr1 = X300_DEFAULT_MAC_ADDR_1,
.gateway = X300_DEFAULT_GATEWAY,
@@ -70,7 +49,7 @@ const void *pick_inited_field(const void *eeprom, const void *def, const size_t
return eeprom;
}
-static void init_network(void)
+static void init_network(x300_eeprom_map_t *eeprom_map)
{
pkt_config = wb_pkt_iface64_init(PKT_RAM0_BASE, 0x1ffc);
u3_net_stack_init(&pkt_config);
@@ -79,21 +58,20 @@ static void init_network(void)
//read everything from eeprom
static const uint8_t eeprom_cmd[2] = {0, 0}; //the command is 16 bits of address offset
- struct x300_eeprom_map eeprom_map = default_map;
wb_i2c_write(I2C1_BASE, MBOARD_EEPROM_ADDR, eeprom_cmd, 2);
- wb_i2c_read(I2C1_BASE, MBOARD_EEPROM_ADDR, (uint8_t *)(&eeprom_map), sizeof(eeprom_map));
+ wb_i2c_read(I2C1_BASE, MBOARD_EEPROM_ADDR, (uint8_t *)(eeprom_map), sizeof(x300_eeprom_map_t));
//determine interface number
const size_t eth0no = wb_peek32(SR_ADDR(RB0_BASE, RB_SFP0_TYPE))? 2 : 0;
const size_t eth1no = wb_peek32(SR_ADDR(RB0_BASE, RB_SFP1_TYPE))? 3 : 1;
//pick the address from eeprom or default
- const eth_mac_addr_t *my_mac0 = (const eth_mac_addr_t *)pick_inited_field(&eeprom_map.mac_addr0, &default_map.mac_addr0, 6);
- const eth_mac_addr_t *my_mac1 = (const eth_mac_addr_t *)pick_inited_field(&eeprom_map.mac_addr1, &default_map.mac_addr1, 6);
- const struct ip_addr *my_ip0 = (const struct ip_addr *)pick_inited_field(&eeprom_map.ip_addr[eth0no], &default_map.ip_addr[eth0no], 4);
- const struct ip_addr *subnet0 = (const struct ip_addr *)pick_inited_field(&eeprom_map.subnet[eth0no], &default_map.subnet[eth0no], 4);
- const struct ip_addr *my_ip1 = (const struct ip_addr *)pick_inited_field(&eeprom_map.ip_addr[eth1no], &default_map.ip_addr[eth1no], 4);
- const struct ip_addr *subnet1 = (const struct ip_addr *)pick_inited_field(&eeprom_map.subnet[eth1no], &default_map.subnet[eth1no], 4);
+ const eth_mac_addr_t *my_mac0 = (const eth_mac_addr_t *)pick_inited_field(&eeprom_map->mac_addr0, &default_map.mac_addr0, 6);
+ const eth_mac_addr_t *my_mac1 = (const eth_mac_addr_t *)pick_inited_field(&eeprom_map->mac_addr1, &default_map.mac_addr1, 6);
+ const struct ip_addr *my_ip0 = (const struct ip_addr *)pick_inited_field(&eeprom_map->ip_addr[eth0no], &default_map.ip_addr[eth0no], 4);
+ const struct ip_addr *subnet0 = (const struct ip_addr *)pick_inited_field(&eeprom_map->subnet[eth0no], &default_map.subnet[eth0no], 4);
+ const struct ip_addr *my_ip1 = (const struct ip_addr *)pick_inited_field(&eeprom_map->ip_addr[eth1no], &default_map.ip_addr[eth1no], 4);
+ const struct ip_addr *subnet1 = (const struct ip_addr *)pick_inited_field(&eeprom_map->subnet[eth1no], &default_map.subnet[eth1no], 4);
//init eth0
u3_net_stack_init_eth(0, my_mac0, my_ip0, subnet0);
@@ -126,7 +104,7 @@ static uint32_t get_counter_val()
return wb_peek32(SR_ADDR(RB0_BASE, RB_COUNTER));
}
-void x300_init(void)
+void x300_init(x300_eeprom_map_t *eeprom_map)
{
//first - uart
wb_uart_init(UART0_BASE, CPU_CLOCK/UART0_BAUD);
@@ -153,7 +131,7 @@ void x300_init(void)
wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), SW_RST_PHY);
//setup net stack and eth state machines
- init_network();
+ init_network(eeprom_map);
//phy reset release
wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), 0);
diff --git a/firmware/usrp3/x300/x300_init.h b/firmware/usrp3/x300/x300_init.h
index 324033779..2e93340f6 100644
--- a/firmware/usrp3/x300/x300_init.h
+++ b/firmware/usrp3/x300/x300_init.h
@@ -4,7 +4,10 @@
#ifndef INCLUDED_B250_INIT_H
#define INCLUDED_B250_INIT_H
-void x300_init(void);
+#include "x300_defs.h"
+#include "x300_fw_common.h"
+
+void x300_init(x300_eeprom_map_t *eeprom_map);
void x300_serial_loader_run1(void);
diff --git a/firmware/usrp3/x300/x300_main.c b/firmware/usrp3/x300/x300_main.c
index f255fe96c..c5e4fc88a 100644
--- a/firmware/usrp3/x300/x300_main.c
+++ b/firmware/usrp3/x300/x300_main.c
@@ -240,7 +240,7 @@ static void handle_claim(void)
last_time = shmem[X300_FW_SHMEM_CLAIM_TIME];
//the claim has timed out after 2 seconds
- if (timeout > 2000) shmem[X300_FW_SHMEM_CLAIM_STATUS] = 0;
+ if (timeout > 200) shmem[X300_FW_SHMEM_CLAIM_STATUS] = 0;
}
/***********************************************************************
@@ -264,36 +264,17 @@ static uint32_t get_xbar_total(const uint32_t port)
return total;
}
-static size_t popcntll(uint64_t num)
-{
- size_t total = 0;
- for (size_t i = 0; i < sizeof(num)*8; i++)
- {
- total += (num >> i) & 0x1;
- }
- return total;
-}
-
static void update_leds(void)
{
- //update activity status for all ports
- uint64_t activity_shreg[16];
- for (uint32_t i = 0; i < 16; i++)
- {
- static uint32_t last_total[16];
- const uint32_t total = get_xbar_total(i);
- activity_shreg[i] <<= 1;
- activity_shreg[i] |= (total == last_total[i])? 0 : 1;
- last_total[i] = total;
- }
-
- static uint32_t counter = 0;
- counter++;
+ static uint32_t last_total0 = 0;
+ static uint32_t last_total1 = 0;
+ const uint32_t total0 = get_xbar_total(0);
+ const uint32_t total1 = get_xbar_total(1);
+ const bool act0 = (total0 != last_total0);
+ const bool act1 = (total1 != last_total1);
+ last_total0 = total0;
+ last_total1 = total1;
- const size_t cnt0 = popcntll(activity_shreg[0]);
- const size_t cnt1 = popcntll(activity_shreg[1]);
- const bool act0 = cnt0*8 > (counter % 64);
- const bool act1 = cnt1*8 > (counter % 64);
const bool link0 = ethernet_get_link_up(0);
const bool link1 = ethernet_get_link_up(1);
const bool claimed = shmem[X300_FW_SHMEM_CLAIM_STATUS];
@@ -314,7 +295,7 @@ static void update_leds(void)
static void garp(void)
{
static size_t count = 0;
- if (count++ < 60000) return; //60 seconds
+ if (count++ < 3000) return; //30 seconds
count = 0;
for (size_t e = 0; e < ethernet_ninterfaces(); e++)
{
@@ -428,7 +409,7 @@ static void handle_link_state(void)
**********************************************************************/
int main(void)
{
- x300_init();
+ x300_init((x300_eeprom_map_t *)&shmem[X300_FW_SHMEM_IDENT]);
u3_net_stack_register_udp_handler(X300_FW_COMMS_UDP_PORT, &handle_udp_fw_comms);
u3_net_stack_register_udp_handler(X300_VITA_UDP_PORT, &handle_udp_prog_framer);
u3_net_stack_register_udp_handler(X300_FPGA_PROG_UDP_PORT, &handle_udp_fpga_prog);
@@ -438,10 +419,10 @@ int main(void)
while(true)
{
- //jobs that happen once every ms
+ //jobs that happen once every 10ms
const uint32_t ticks_now = wb_peek32(SR_ADDR(RB0_BASE, RB_COUNTER));
const uint32_t ticks_passed = ticks_now - last_cronjob;
- static const uint32_t tick_delta = CPU_CLOCK/1000;
+ static const uint32_t tick_delta = CPU_CLOCK/100;
if (ticks_passed > tick_delta)
{
poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events.
@@ -450,7 +431,7 @@ int main(void)
handle_claim(); //deal with the host claim register
update_leds(); //run the link and activity leds
garp(); //send periodic garps
- last_cronjob = wb_peek32(SR_ADDR(RB0_BASE, RB_COUNTER));
+ last_cronjob = ticks_now;
}
//run the network stack - poll and handle
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index dd9b51e2b..40c92b856 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -80,7 +80,6 @@ ELSEIF(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
ENDIF()
ENDIF()
-
IF(CMAKE_VERSION VERSION_LESS "3.1")
IF(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
SET(CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
@@ -289,7 +288,7 @@ ENDIF(MSVC)
SET(Boost_ADDITIONAL_VERSIONS
"1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.48.0" "1.49" "1.50.0" "1.50"
"1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" "1.55.0" "1.55"
- "1.56.0" "1.56" "1.57" "1.57" "1.58" "1.59" "1.60"
+ "1.56.0" "1.56" "1.57" "1.57" "1.58" "1.59" "1.60" "1.61"
)
FIND_PACKAGE(Boost 1.53 COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
@@ -358,8 +357,8 @@ UHD_INSTALL(FILES
#{{{IMG_SECTION
# This section is written automatically by /images/create_imgs_package.py
# Any manual changes in here will be overwritten.
-SET(UHD_IMAGES_MD5SUM "a3626ec5f123a4179552be08a50dccc2")
-SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.010.001.000-42-gd0a60fea.zip")
+SET(UHD_IMAGES_MD5SUM "9641027408a4bbd478ad221d3dae1cfd")
+SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.010.001.001-rc1.zip")
#}}}
########################################################################
diff --git a/host/docs/vrt_chdr.dox b/host/docs/vrt_chdr.dox
index 560f0b6a3..a2d36c93e 100644
--- a/host/docs/vrt_chdr.dox
+++ b/host/docs/vrt_chdr.dox
@@ -7,8 +7,8 @@ If one were to sniff Ethernet traffic between a USRP and a PC, the packets would
radio transport protocol.
For USRP devices, two radio transport protocols are relevant: VRT (the VITA Radio Transport protocol)
-and CVITA (compressed VITA), also known as CHDR. Generation-3 devices and the B200 use CHDR, the rest
-use VRT.
+and CHDR (compressed header, an Ettus-specific protocol).
+Generation-3 devices and the B200 use CHDR, the rest use VRT.
\section rtp_vrt VRT
@@ -19,13 +19,12 @@ VRT is a very verbose standard, and only a subset is implemented in UHD/USRPs.
The full standard is available from the VITA website: http://www.vita.com .
-\section rtp_chdr CVITA (CHDR)
+\section rtp_chdr CHDR
For the third generation of Ettus devices, a new type transport protocol was designed.
It reduces the complexity of the original standard and uses a fixed-length 64-Bit header
-for everything except the timestamp. Because this is a "compressed" form of VITA, it
-was dubbed "Compressed VITA" (CVITA). The compressed header is called CHDR, which is why
-the protocol is often called CHDR itself (pronounced like the cheese "cheddar").
+for everything except the timestamp. Because it is "compressed" into a 64-bit heaer, it
+was dubbed CHDR (pronounced like the cheese "cheddar").
By compressing all information into a 64-bit line, the header can efficiently be parsed
in newer FPGAs, where the common streaming protocol is 64-Bit AXI. The first line in a
@@ -33,7 +32,7 @@ packet already provides all necessary information to proceed.
Some CHDR-specific functions can be found in: uhd::transport::vrt::chdr.
-The form of a CVITA packet is the following:
+The form of a CHDR packet is the following:
Address (Bytes) | Length (Bytes) | Payload
----------------|----------------|----------------------------
@@ -76,7 +75,7 @@ for Ethernet links as well as USB (e.g., for the B210).
Relevant code sections for the radio transport layer are:
* uhd::transport::vrt - Namespace for radio transport protocol related functions and definitions
-* uhd::transport::vrt::chdr - Sub-namespace specifically for CVITA/CHDR
+* uhd::transport::vrt::chdr - Sub-namespace specifically for CHDR
* uhd::sid_t - Datatype to represent SIDs
*/
diff --git a/host/include/uhd/rfnoc/blocks/ddc.xml b/host/include/uhd/rfnoc/blocks/ddc.xml
index a88616117..13b9414bd 100644
--- a/host/include/uhd/rfnoc/blocks/ddc.xml
+++ b/host/include/uhd/rfnoc/blocks/ddc.xml
@@ -5,7 +5,7 @@
<key>DDC</key>
<!--There can be several of these:-->
<ids>
- <id revision="0">DDC0</id>
+ <id revision="0">DDC0000000000000</id>
</ids>
<!-- Registers -->
<registers>
diff --git a/host/include/uhd/transport/chdr.hpp b/host/include/uhd/transport/chdr.hpp
index fa2ae074e..3c85056d7 100644
--- a/host/include/uhd/transport/chdr.hpp
+++ b/host/include/uhd/transport/chdr.hpp
@@ -22,9 +22,9 @@
namespace uhd{ namespace transport{ namespace vrt{
-/*! \brief CVITA/CHDR related function
+/*! \brief CHDR related function
*
- * See \ref rtp_chdr for details on the CVITA/CHDR protocol.
+ * See \ref rtp_chdr for details on the CHDR protocol.
*
* All packers take the host format into account. Choose the _le functions
* if the transport uses little endian format (e.g. PCIe) and the _be
@@ -46,7 +46,7 @@ namespace uhd{ namespace transport{ namespace vrt{
*/
namespace chdr{
- //! The maximum number of 64-bit words in a CVITA header
+ //! The maximum number of 64-bit words in a CHDR header
static const size_t max_if_hdr_words64 = 2; // CHDR + tsf (fractional timestamp)
/*!
diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp
index 7d0123c42..1e0f4b2e0 100644
--- a/host/include/uhd/transport/vrt_if_packet.hpp
+++ b/host/include/uhd/transport/vrt_if_packet.hpp
@@ -57,7 +57,7 @@ namespace vrt{
PACKET_TYPE_IF_EXT = 0x1,
PACKET_TYPE_CONTEXT = 0x2, //extension context: has_sid = true
- // CVITA language:
+ // CHDR language:
//PACKET_TYPE_DATA = 0x0, // Data
PACKET_TYPE_FC = 0x1, // Flow control
PACKET_TYPE_ACK = 0x1, // Flow control (ack)
diff --git a/host/lib/experts/expert_container.cpp b/host/lib/experts/expert_container.cpp
index 1d945aa42..b9c78f9f5 100644
--- a/host/lib/experts/expert_container.cpp
+++ b/host/lib/experts/expert_container.cpp
@@ -294,11 +294,11 @@ protected:
EX_LOG(0, str(boost::format("add_data_node(%s)") % data_node->get_name()));
if (data_node->get_class() == CLASS_WORKER) {
throw uhd::runtime_error("Supplied node " + data_node->get_name() + " is not a data/property node.");
- delete data_node;
+ // Throw leaves data_node undeleted
}
if (_datanode_map.find(data_node->get_name()) != _datanode_map.end()) {
throw uhd::runtime_error("Data node with name " + data_node->get_name() + " already exists");
- delete data_node;
+ // Throw leaves data node undeleted
}
try {
@@ -335,11 +335,9 @@ protected:
EX_LOG(0, str(boost::format("add_worker(%s)") % worker->get_name()));
if (worker->get_class() != CLASS_WORKER) {
throw uhd::runtime_error("Supplied node " + worker->get_name() + " is not a worker node.");
- delete worker;
}
if (_worker_map.find(worker->get_name()) != _worker_map.end()) {
throw uhd::runtime_error("Resolver with name " + worker->get_name() + " already exists.");
- delete worker;
}
try {
diff --git a/host/lib/rfnoc/block_ctrl_base.cpp b/host/lib/rfnoc/block_ctrl_base.cpp
index fa4928a69..4ee577891 100644
--- a/host/lib/rfnoc/block_ctrl_base.cpp
+++ b/host/lib/rfnoc/block_ctrl_base.cpp
@@ -504,7 +504,6 @@ std::string block_ctrl_base::get_arg(const std::string &key, const size_t port)
}
UHD_THROW_INVALID_CODE_PATH();
- return "";
}
std::string block_ctrl_base::get_arg_type(const std::string &key, const size_t port) const
diff --git a/host/lib/rfnoc/nocscript/function_table.cpp b/host/lib/rfnoc/nocscript/function_table.cpp
index bebceb8dc..a4e36c1a1 100644
--- a/host/lib/rfnoc/nocscript/function_table.cpp
+++ b/host/lib/rfnoc/nocscript/function_table.cpp
@@ -31,7 +31,7 @@ class function_table_impl : public function_table
expression::type_t return_type;
function_ptr function;
- function_info() {};
+ function_info(): return_type(expression::TYPE_INT) {};
function_info(const expression::type_t return_type_, const function_ptr &function_)
: return_type(return_type_), function(function_)
{};
diff --git a/host/lib/rfnoc/xports.hpp b/host/lib/rfnoc/xports.hpp
index 1ce05c6c8..7bd4f2fc8 100644
--- a/host/lib/rfnoc/xports.hpp
+++ b/host/lib/rfnoc/xports.hpp
@@ -25,6 +25,7 @@ namespace uhd {
*/
struct both_xports_t
{
+ both_xports_t(): recv_buff_size(0), send_buff_size(0) {}
uhd::transport::zero_copy_if::sptr recv;
uhd::transport::zero_copy_if::sptr send;
size_t recv_buff_size;
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
index 45ebf78bf..e2ed2c77d 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
@@ -491,8 +491,8 @@ double ad9361_device_t::_calibrate_secondary_tx_filter(double req_rfbw)
} else if ((bbbw_mhz * 2) > 24) {
reg0d0 = 0x57;
} else {
- throw uhd::runtime_error("[ad9361_device_t] Cal2ndTxFil: INVALID_CODE_PATH bad bbbw_mhz");
reg0d0 = 0x00;
+ throw uhd::runtime_error("[ad9361_device_t] Cal2ndTxFil: INVALID_CODE_PATH bad bbbw_mhz");
}
/* Translate resistor values to register settings. */
@@ -996,8 +996,8 @@ void ad9361_device_t::_program_gain_table() {
gain_table = gain_table_4000mhz_to_6000mhz;
new_gain_table = 3;
} else {
- throw uhd::runtime_error("[ad9361_device_t] Wrong _rx_freq value");
new_gain_table = 1;
+ throw uhd::runtime_error("[ad9361_device_t] Wrong _rx_freq value");
}
/* Only re-program the gain table if there has been a band change. */
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h
index ae065d78e..f3d24d6b9 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h
@@ -40,7 +40,15 @@ public:
enum chain_t { CHAIN_1, CHAIN_2, CHAIN_BOTH };
ad9361_device_t(ad9361_params::sptr client, ad9361_io::sptr io_iface) :
- _client_params(client), _io_iface(io_iface) {
+ _client_params(client), _io_iface(io_iface),
+ _bbpll_freq(0.0), _adcclock_freq(0.0), _req_clock_rate(0.0),
+ _req_coreclk(0.0), _rx_bbf_tunediv(0), _curr_gain_table(0),
+ _rx1_gain(0.0), _rx2_gain(0.0), _tx1_gain(0.0), _tx2_gain(0.0),
+ _tfir_factor(0), _rfir_factor(0),
+ _rx1_agc_mode(GAIN_MODE_MANUAL), _rx2_agc_mode(GAIN_MODE_MANUAL),
+ _rx1_agc_enable(false), _rx2_agc_enable(false),
+ _use_dc_offset_tracking(false), _use_iq_balance_tracking(false)
+ {
/*
* This Boost.Assign to_container() workaround is necessary because STL containers
@@ -213,7 +221,11 @@ private: //Methods
void _set_filter_lp_tia_sec(direction_t direction, filter_info_base::sptr filter);
private: //Members
- typedef struct {
+ struct chip_regs_t
+ {
+ chip_regs_t():
+ vcodivs(0), inputsel(0), rxfilt(0), txfilt(0),
+ bbpll(0), bbftune_config(0), bbftune_mode(0) {}
uint8_t vcodivs;
uint8_t inputsel;
uint8_t rxfilt;
@@ -221,7 +233,7 @@ private: //Members
uint8_t bbpll;
uint8_t bbftune_config;
uint8_t bbftune_mode;
- } chip_regs_t;
+ };
struct filter_query_helper
{
diff --git a/host/lib/usrp/cores/rx_frontend_core_3000.cpp b/host/lib/usrp/cores/rx_frontend_core_3000.cpp
index 1c4674a8a..e7d25eb8c 100644
--- a/host/lib/usrp/cores/rx_frontend_core_3000.cpp
+++ b/host/lib/usrp/cores/rx_frontend_core_3000.cpp
@@ -170,7 +170,6 @@ public:
default:
return _adc_rate;
}
- return _adc_rate;
}
private:
diff --git a/host/lib/usrp/dboard/twinrx/twinrx_gain_tables.cpp b/host/lib/usrp/dboard/twinrx/twinrx_gain_tables.cpp
index 5cc8b49f3..783ded8cc 100644
--- a/host/lib/usrp/dboard/twinrx/twinrx_gain_tables.cpp
+++ b/host/lib/usrp/dboard/twinrx/twinrx_gain_tables.cpp
@@ -836,7 +836,6 @@ const twinrx_gain_table twinrx_gain_table::lookup_table
}
}
throw runtime_error("NO GAIN TABLE SELECTED");
- return twinrx_gain_table(HIGHBAND1_TABLE);
}
const twinrx_gain_config_t& twinrx_gain_table::find_by_index(size_t index) const {
diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp
index b3a34afe3..bb98b1031 100644
--- a/host/lib/usrp/device3/device3_io_impl.cpp
+++ b/host/lib/usrp/device3/device3_io_impl.cpp
@@ -38,7 +38,7 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::transport;
-//! CVITA uses 12-Bit sequence numbers
+//! CHDR uses 12-Bit sequence numbers
static const uint32_t HW_SEQ_NUM_MASK = 0xfff;
diff --git a/host/lib/usrp/e300/e300_global_regs.hpp b/host/lib/usrp/e300/e300_global_regs.hpp
index 3b6b26239..c56cff298 100644
--- a/host/lib/usrp/e300/e300_global_regs.hpp
+++ b/host/lib/usrp/e300/e300_global_regs.hpp
@@ -24,6 +24,7 @@
namespace uhd { namespace usrp { namespace e300 {
struct global_regs_transaction_t {
+ global_regs_transaction_t(): is_poke(0), addr(0), data(0), pad(0) {}
uint32_t is_poke;
uint32_t addr;
uint32_t data;
diff --git a/host/lib/usrp/e300/e300_i2c.hpp b/host/lib/usrp/e300/e300_i2c.hpp
index 98a1f80aa..1c5e06bba 100644
--- a/host/lib/usrp/e300/e300_i2c.hpp
+++ b/host/lib/usrp/e300/e300_i2c.hpp
@@ -27,6 +27,7 @@
namespace uhd { namespace usrp { namespace e300 {
struct i2c_transaction_t {
+ i2c_transaction_t(): reg(0), addr(0), data(0), type(0) {};
uint16_t reg;
uint8_t addr;
uint8_t data;
diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp
index 632424438..50d78fdd4 100644
--- a/host/lib/usrp/e300/e300_impl.hpp
+++ b/host/lib/usrp/e300/e300_impl.hpp
@@ -189,7 +189,8 @@ private: // types
{
gpio_t() : pps_sel(global_regs::PPS_INT),
mimo(0), codec_arst(0), tx_bandsels(0),
- rx_bandsel_a(0), rx_bandsel_b(0), rx_bandsel_c(0)
+ rx_bandsel_a(0), rx_bandsel_b(0), rx_bandsel_c(0),
+ time_sync(0)
{}
uint32_t pps_sel;
diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp
index 5c0014a89..0e6cb8574 100644
--- a/host/lib/usrp/mboard_eeprom.cpp
+++ b/host/lib/usrp/mboard_eeprom.cpp
@@ -235,52 +235,88 @@ struct x300_eeprom_map
static void load_x300(mboard_eeprom_t &mb_eeprom, i2c_iface &iface)
{
+ byte_vector_t bytes = iface.read_eeprom(X300_EEPROM_ADDR, 0, sizeof (struct x300_eeprom_map));
+
+ if (bytes.size() == 0)
+ {
+ return;
+ }
+
//extract the revision number
mb_eeprom["revision"] = uint16_bytes_to_string(
- iface.read_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, revision), 2)
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, revision),
+ bytes.begin() + (offsetof(x300_eeprom_map, revision)+2))
);
//extract the revision compat number
mb_eeprom["revision_compat"] = uint16_bytes_to_string(
- iface.read_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, revision_compat), 2)
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, revision_compat),
+ bytes.begin() + (offsetof(x300_eeprom_map, revision_compat)+2))
);
//extract the product code
mb_eeprom["product"] = uint16_bytes_to_string(
- iface.read_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, product), 2)
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, product),
+ bytes.begin() + (offsetof(x300_eeprom_map, product)+2))
);
//extract the mac addresses
- mb_eeprom["mac-addr0"] = mac_addr_t::from_bytes(iface.read_eeprom(
- X300_EEPROM_ADDR, offsetof(x300_eeprom_map, mac_addr0), 6
- )).to_string();
- mb_eeprom["mac-addr1"] = mac_addr_t::from_bytes(iface.read_eeprom(
- X300_EEPROM_ADDR, offsetof(x300_eeprom_map, mac_addr1), 6
- )).to_string();
+ mb_eeprom["mac-addr0"] = mac_addr_t::from_bytes(
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, mac_addr0),
+ bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0)+6))
+ ).to_string();
+ mb_eeprom["mac-addr1"] = mac_addr_t::from_bytes(
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, mac_addr1),
+ bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1)+6))
+ ).to_string();
//extract the ip addresses
boost::asio::ip::address_v4::bytes_type ip_addr_bytes;
- byte_copy(iface.read_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), 4), ip_addr_bytes);
+ byte_copy(
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, gateway),
+ bytes.begin() + (offsetof(x300_eeprom_map, gateway)+4)),
+ ip_addr_bytes
+ );
mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
for (size_t i = 0; i < 4; i++)
{
const std::string n(1, i+'0');
- byte_copy(iface.read_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, ip_addr)+(i*4), 4), ip_addr_bytes);
+ byte_copy(
+ byte_vector_t(
+ bytes.begin() + (offsetof(x300_eeprom_map, ip_addr)+(i*4)),
+ bytes.begin() + (offsetof(x300_eeprom_map, ip_addr)+(i*4)+4)),
+ ip_addr_bytes
+ );
mb_eeprom["ip-addr"+n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
- byte_copy(iface.read_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, subnet)+(i*4), 4), ip_addr_bytes);
+ byte_copy(
+ byte_vector_t(
+ bytes.begin() + (offsetof(x300_eeprom_map, subnet)+(i*4)),
+ bytes.begin() + (offsetof(x300_eeprom_map, subnet)+(i*4)+4)),
+ ip_addr_bytes
+ );
mb_eeprom["subnet"+n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
}
//extract the serial
- mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom(
- X300_EEPROM_ADDR, offsetof(x300_eeprom_map, serial), SERIAL_LEN
- ));
+ mb_eeprom["serial"] = bytes_to_string(
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, serial),
+ bytes.begin() + (offsetof(x300_eeprom_map, serial)+SERIAL_LEN))
+ );
//extract the name
- mb_eeprom["name"] = bytes_to_string(iface.read_eeprom(
- X300_EEPROM_ADDR, offsetof(x300_eeprom_map, name), NAME_MAX_LEN
- ));
+ mb_eeprom["name"] = bytes_to_string(
+ byte_vector_t(
+ bytes.begin() + offsetof(x300_eeprom_map, name),
+ bytes.begin() + (offsetof(x300_eeprom_map, name)+NAME_MAX_LEN))
+ );
}
static void store_x300(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface)
diff --git a/host/lib/usrp/n230/n230_resource_manager.cpp b/host/lib/usrp/n230/n230_resource_manager.cpp
index 826db5ed2..b96de542a 100644
--- a/host/lib/usrp/n230/n230_resource_manager.cpp
+++ b/host/lib/usrp/n230/n230_resource_manager.cpp
@@ -487,10 +487,11 @@ bool n230_resource_manager::_radio_data_loopback_self_test(wb_iface::sptr iface)
const uint32_t rb_tx = uint32_t(rb_word64 >> 32);
const uint32_t rb_rx = uint32_t(rb_word64 & 0xffffffff);
test_fail = word32 != rb_tx or word32 != rb_rx;
- if (test_fail)
+ if (test_fail){
UHD_MSG(fastpath) << boost::format("mismatch (exp:%x, got:%x and %x)... ") % word32 % rb_tx % rb_rx;
break; //exit loop on any failure
}
+ }
/* Zero out the idle data. */
iface->poke32(fpga::sr_addr(fpga::SR_RADIO_CODEC_IDLE), 0);
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 9fde9a626..1dafe5721 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -182,7 +182,7 @@ void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
switch(unit){
case UNIT_RX: _clock_ctrl->enable_rx_dboard_clock(enb); return;
case UNIT_TX: _clock_ctrl->enable_tx_dboard_clock(enb); return;
- case UNIT_BOTH: set_clock_enabled(UNIT_RX, enb); set_clock_enabled(UNIT_TX, enb); return;
+ default: UHD_THROW_INVALID_CODE_PATH();
}
}
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 199436fa2..224519944 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -433,7 +433,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){
;
const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size;
const size_t bpi = convert::get_bytes_per_item(args.otw_format);
- const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi));
+ const size_t spp = args.args.cast<size_t>("spp", bpp/bpi);
//make the new streamer given the samples per packet
boost::shared_ptr<sph::recv_packet_streamer> my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp);
diff --git a/host/lib/usrp/usrp2/n200_image_loader.cpp b/host/lib/usrp/usrp2/n200_image_loader.cpp
index 16cc7b08a..c68484600 100644
--- a/host/lib/usrp/usrp2/n200_image_loader.cpp
+++ b/host/lib/usrp/usrp2/n200_image_loader.cpp
@@ -324,7 +324,7 @@ static void n200_validate_fpga_image(n200_session_t &session){
image_file.seekg(0, std::ios::beg);
image_file.read((char*)test_bytes, 63);
bool is_good = false;
- for(int i = 0; i < 63; i++){
+ for(int i = 0; i < 62; i++){
if(test_bytes[i] == 255) continue;
else if(test_bytes[i] == 170 and
test_bytes[i+1] == 153){
diff --git a/host/lib/usrp/x300/CMakeLists.txt b/host/lib/usrp/x300/CMakeLists.txt
index ea237b008..5f8e83e1c 100644
--- a/host/lib/usrp/x300/CMakeLists.txt
+++ b/host/lib/usrp/x300/CMakeLists.txt
@@ -34,6 +34,7 @@ IF(ENABLE_X300)
${CMAKE_CURRENT_SOURCE_DIR}/x300_dboard_iface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/x300_clock_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/x300_image_loader.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/x300_mb_eeprom.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cdecode.c
)
ENDIF(ENABLE_X300)
diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h
index aae0f769c..b83449666 100644
--- a/host/lib/usrp/x300/x300_fw_common.h
+++ b/host/lib/usrp/x300/x300_fw_common.h
@@ -32,7 +32,7 @@ extern "C" {
#define X300_REVISION_COMPAT 7
#define X300_REVISION_MIN 2
#define X300_FW_COMPAT_MAJOR 5
-#define X300_FW_COMPAT_MINOR 0
+#define X300_FW_COMPAT_MINOR 1
#define X300_FPGA_COMPAT_MAJOR 0x21
//shared memory sections - in between the stack and the program space
@@ -49,6 +49,9 @@ extern "C" {
#define X300_FW_SHMEM_UART_WORDS32 10
#define X300_FW_SHMEM_ROUTE_MAP_ADDR 11
#define X300_FW_SHMEM_ROUTE_MAP_LEN 12
+#define X300_FW_SHMEM_IDENT 13 // (13-39) EEPROM values in use
+#define X300_FW_SHMEM_DEBUG 128
+#define X300_FW_SHMEM_ADDR(offset) X300_FW_SHMEM_BASE + (4 * (offset))
#define X300_FW_NUM_BYTES (1 << 15) //64k
#define X300_FW_COMMS_MTU (1 << 13) //8k
@@ -94,6 +97,30 @@ extern "C" {
typedef struct
{
+ //indentifying numbers
+ unsigned char revision[2];
+ unsigned char product[2];
+ uint8_t _pad0[4];
+
+ //all the mac addrs
+ uint8_t mac_addr0[6];
+ uint8_t _pad1[2];
+ uint8_t mac_addr1[6];
+ uint8_t _pad2[2];
+
+ //all the IP addrs
+ uint32_t gateway;
+ uint32_t subnet[4];
+ uint32_t ip_addr[4];
+ uint8_t _pad3[16];
+
+ //names and serials
+ unsigned char name[23];
+ unsigned char serial[9];
+} x300_eeprom_map_t;
+
+typedef struct
+{
uint32_t flags;
uint32_t sequence;
uint32_t addr;
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index cd85ea141..83c687637 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -18,6 +18,7 @@
#include "x300_impl.hpp"
#include "x300_lvbitx.hpp"
#include "x310_lvbitx.hpp"
+#include "x300_mb_eeprom.hpp"
#include "apply_corrections.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
@@ -121,12 +122,16 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint)
false /* Suppress timeout errors */
);
- if (x300_impl::is_claimed(zpu_ctrl)) continue; //claimed by another process
new_addr["fpga"] = get_fpga_option(zpu_ctrl);
i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE);
- i2c_iface::sptr eeprom16 = zpu_i2c->eeprom16();
- const mboard_eeprom_t mb_eeprom(*eeprom16, "X300");
+ x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c);
+ const mboard_eeprom_t mb_eeprom(*eeprom_iface, "X300");
+ if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER)
+ {
+ // Skip device claimed by another process
+ continue;
+ }
new_addr["name"] = mb_eeprom["name"];
new_addr["serial"] = mb_eeprom["serial"];
switch (x300_impl::get_mb_type_from_eeprom(mb_eeprom)) {
@@ -221,7 +226,6 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu
//We don't put this zpu_ctrl in the registry because we need
//a persistent niriok_proxy associated with the object
}
- if (x300_impl::is_claimed(zpu_ctrl)) continue; //claimed by another process
//Attempt to autodetect the FPGA type
if (not hint.has_key("fpga")) {
@@ -229,8 +233,13 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu
}
i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE);
- i2c_iface::sptr eeprom16 = zpu_i2c->eeprom16();
- const mboard_eeprom_t mb_eeprom(*eeprom16, "X300");
+ x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c);
+ const mboard_eeprom_t mb_eeprom(*eeprom_iface, "X300");
+ if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER)
+ {
+ // Skip device claimed by another process
+ continue;
+ }
new_addr["name"] = mb_eeprom["name"];
new_addr["serial"] = mb_eeprom["serial"];
}
@@ -307,12 +316,7 @@ device_addrs_t x300_find(const device_addr_t &hint_)
{
UHD_MSG(error) << "X300 Network discovery unknown error " << std::endl;
}
- BOOST_FOREACH(const device_addr_t &reply_addr, reply_addrs)
- {
- device_addrs_t new_addrs = x300_find_with_addr(reply_addr);
- addrs.insert(addrs.begin(), new_addrs.begin(), new_addrs.end());
- }
- return addrs;
+ return reply_addrs;
}
if (!hint.has_key("resource"))
@@ -671,6 +675,10 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)));
}
+ // Claim device
+ if (not try_to_claim(mb.zpu_ctrl)) {
+ throw uhd::runtime_error("Failed to claim device");
+ }
mb.claimer_task = uhd::task::make(boost::bind(&x300_impl::claimer_loop, this, mb.zpu_ctrl));
//extract the FW path for the X300
@@ -726,7 +734,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
// setup the mboard eeprom
////////////////////////////////////////////////////////////////////
UHD_MSG(status) << "Loading values from EEPROM..." << std::endl;
- i2c_iface::sptr eeprom16 = mb.zpu_i2c->eeprom16();
+ x300_mb_eeprom_iface::sptr eeprom16 = x300_mb_eeprom_iface::make(mb.zpu_ctrl, mb.zpu_i2c);
if (dev_addr.has_key("blank_eeprom"))
{
UHD_MSG(warning) << "Obliterating the motherboard EEPROM..." << std::endl;
@@ -1002,8 +1010,7 @@ x300_impl::~x300_impl(void)
mb.claimer_task.reset();
{ //Critical section
boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex);
- mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0);
- mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0);
+ release(mb.zpu_ctrl);
//If the process is killed, the entire registry will disappear so we
//don't need to worry about unclean shutdowns here.
get_pcie_zpu_iface_registry().pop(mb.get_pri_eth().addr);
@@ -1457,24 +1464,58 @@ void x300_impl::set_mb_eeprom(i2c_iface::sptr i2c, const mboard_eeprom_t &mb_eep
void x300_impl::claimer_loop(wb_iface::sptr iface)
{
- { //Critical section
- boost::mutex::scoped_lock(claimer_mutex);
- iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), uint32_t(time(NULL)));
- iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash());
- }
+ claim(iface);
boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); //1 second
}
-bool x300_impl::is_claimed(wb_iface::sptr iface)
+x300_impl::claim_status_t x300_impl::claim_status(wb_iface::sptr iface)
{
- boost::mutex::scoped_lock(claimer_mutex);
-
- //If timed out then device is definitely unclaimed
- if (iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_STATUS)) == 0)
- return false;
+ //If timed out, then device is definitely unclaimed
+ if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0)
+ return UNCLAIMED;
//otherwise check claim src to determine if another thread with the same src has claimed the device
- return iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC)) != get_process_hash();
+ uint32_t hash = iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC));
+ return (hash == get_process_hash() ? CLAIMED_BY_US : CLAIMED_BY_OTHER);
+}
+
+void x300_impl::claim(wb_iface::sptr iface)
+{
+ iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_TIME), uint32_t(time(NULL)));
+ iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC), get_process_hash());
+}
+
+bool x300_impl::try_to_claim(wb_iface::sptr iface, long timeout)
+{
+ boost::system_time start_time = boost::get_system_time();
+ while (1)
+ {
+ claim_status_t status = claim_status(iface);
+ if (status == UNCLAIMED)
+ {
+ claim(iface);
+ // It takes the claimer 10ms to update status, so wait 20ms before verifying claim
+ boost::this_thread::sleep(boost::posix_time::milliseconds(20));
+ continue;
+ }
+ if (status == CLAIMED_BY_US)
+ {
+ break;
+ }
+ if (boost::get_system_time() - start_time > boost::posix_time::milliseconds(timeout))
+ {
+ // Another process owns the device - give up
+ return false;
+ }
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ }
+ return true;
+}
+
+void x300_impl::release(wb_iface::sptr iface)
+{
+ iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_TIME), 0);
+ iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC), 0);
}
/***********************************************************************
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 53ef012d4..55b055d44 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -129,9 +129,12 @@ public:
void setup_mb(const size_t which, const uhd::device_addr_t &);
~x300_impl(void);
- // used by x300_find_with_addr to find X300 devices.
- static boost::mutex claimer_mutex; //All claims and checks in this process are serialized
- static bool is_claimed(uhd::wb_iface::sptr);
+ // device claim functions
+ enum claim_status_t {UNCLAIMED, CLAIMED_BY_US, CLAIMED_BY_OTHER};
+ static claim_status_t claim_status(uhd::wb_iface::sptr iface);
+ static void claim(uhd::wb_iface::sptr iface);
+ static bool try_to_claim(uhd::wb_iface::sptr iface, long timeout = 2000);
+ static void release(uhd::wb_iface::sptr iface);
enum x300_mboard_t {
USRP_X300_MB, USRP_X310_MB, UNKNOWN
diff --git a/host/lib/usrp/x300/x300_mb_eeprom.cpp b/host/lib/usrp/x300/x300_mb_eeprom.cpp
new file mode 100644
index 000000000..e39b36af8
--- /dev/null
+++ b/host/lib/usrp/x300/x300_mb_eeprom.cpp
@@ -0,0 +1,190 @@
+//
+// Copyright 2013-2016 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/>.
+//
+
+/*
+ * x300_mb_eeprom_iface
+ * This interface was created to prevent MB EEPROM corruption while reading
+ * data during discovery. For devices with firmware version newer than 5.0,
+ * the EEPROM data is read into firmware memory and available without
+ * claiming the device. For devices with firmware versions 5.0 and older,
+ * the code makes sure to claim the device before driving the I2C bus. This
+ * has the unfortunate side effect of preventing multiple processes from
+ * discovering the device simultaneously, but is far better than having EEPROM
+ * corruption.
+ */
+
+#include "x300_mb_eeprom.hpp"
+#include "x300_fw_common.h"
+#include "x300_regs.hpp"
+#include "x300_impl.hpp"
+#include <uhd/exception.hpp>
+#include <uhd/utils/platform.hpp>
+#include <uhd/utils/msg.hpp>
+#include <uhd/utils/byteswap.hpp>
+#include <boost/thread.hpp>
+
+using namespace uhd;
+
+static const uint32_t X300_FW_SHMEM_IDENT_MIN_VERSION = 0x50001;
+
+class x300_mb_eeprom_iface_impl : public x300_mb_eeprom_iface
+{
+public:
+
+ x300_mb_eeprom_iface_impl(wb_iface::sptr wb, i2c_iface::sptr i2c) : _wb(wb), _i2c(i2c)
+ {
+ _compat_num = _wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_COMPAT_NUM));
+ }
+
+ ~x300_mb_eeprom_iface_impl()
+ {
+ /* NOP */
+ }
+
+ /*!
+ * Write bytes over the i2c.
+ * \param addr the address
+ * \param buf the vector of bytes
+ */
+ void write_i2c(
+ uint16_t addr,
+ const byte_vector_t &buf
+ )
+ {
+ UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR);
+ if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US)
+ {
+ throw uhd::io_error("Attempted to write MB EEPROM without claim to device.");
+ }
+ _i2c->write_i2c(addr, buf);
+ }
+
+ /*!
+ * Read bytes over the i2c.
+ * \param addr the address
+ * \param num_bytes number of bytes to read
+ * \return a vector of bytes
+ */
+ byte_vector_t read_i2c(
+ uint16_t addr,
+ size_t num_bytes
+ )
+ {
+ UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR);
+ byte_vector_t bytes;
+ if (_compat_num > X300_FW_SHMEM_IDENT_MIN_VERSION)
+ {
+ bytes = read_eeprom(addr, 0, num_bytes);
+ } else {
+ x300_impl::claim_status_t status = x300_impl::claim_status(_wb);
+ // Claim device before driving the I2C bus
+ if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb))
+ {
+ bytes = _i2c->read_i2c(addr, num_bytes);
+ if (status != x300_impl::CLAIMED_BY_US)
+ {
+ // We didn't originally have the claim, so give it up
+ x300_impl::release(_wb);
+ }
+ }
+ }
+ return bytes;
+ }
+
+ /*!
+ * Write bytes to an eeprom.
+ * \param addr the address
+ * \param offset byte offset
+ * \param buf the vector of bytes
+ */
+ void write_eeprom(
+ uint16_t addr,
+ uint16_t offset,
+ const byte_vector_t &buf
+ )
+ {
+ UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR);
+ if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US)
+ {
+ throw uhd::io_error("Attempted to write MB EEPROM without claim to device.");
+ }
+ _i2c->write_eeprom(addr, offset, buf);
+ }
+
+ /*!
+ * Read bytes from an eeprom.
+ * \param addr the address
+ * \param offset byte offset
+ * \param num_bytes number of bytes to read
+ * \return a vector of bytes
+ */
+ byte_vector_t read_eeprom(
+ uint16_t addr,
+ uint16_t offset,
+ size_t num_bytes
+ )
+ {
+ UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR);
+ byte_vector_t bytes;
+ x300_impl::claim_status_t status = x300_impl::claim_status(_wb);
+ if (_compat_num >= X300_FW_SHMEM_IDENT_MIN_VERSION)
+ {
+ // Get MB EEPROM data from firmware memory
+ if (num_bytes == 0) return bytes;
+
+ size_t bytes_read = 0;
+ for (size_t word = offset / 4; bytes_read < num_bytes; word++)
+ {
+ uint32_t value = byteswap(_wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_IDENT + word)));
+ for (size_t byte = offset % 4; byte < 4 and bytes_read < num_bytes; byte++)
+ {
+ bytes.push_back(uint8_t((value >> (byte * 8)) & 0xff));
+ bytes_read++;
+ }
+ }
+ } else {
+ // Claim device before driving the I2C bus
+ if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb))
+ {
+ bytes = _i2c->read_eeprom(addr, offset, num_bytes);
+ if (status != x300_impl::CLAIMED_BY_US)
+ {
+ // We didn't originally have the claim, so give it up
+ x300_impl::release(_wb);
+ }
+ }
+ }
+ return bytes;
+ }
+
+
+private:
+ wb_iface::sptr _wb;
+ i2c_iface::sptr _i2c;
+ uint32_t _compat_num;
+};
+
+x300_mb_eeprom_iface::~x300_mb_eeprom_iface(void)
+{
+ /* NOP */
+}
+
+x300_mb_eeprom_iface::sptr x300_mb_eeprom_iface::make(wb_iface::sptr wb, i2c_iface::sptr i2c)
+{
+ return boost::make_shared<x300_mb_eeprom_iface_impl>(wb, i2c->eeprom16());
+}
+
diff --git a/host/lib/usrp/x300/x300_mb_eeprom.hpp b/host/lib/usrp/x300/x300_mb_eeprom.hpp
new file mode 100644
index 000000000..0649855c6
--- /dev/null
+++ b/host/lib/usrp/x300/x300_mb_eeprom.hpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2016 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_X300_MB_EEPROM_HPP
+#define INCLUDED_X300_MB_EEPROM_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/serial.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <uhd/types/wb_iface.hpp>
+
+class x300_mb_eeprom_iface : public uhd::i2c_iface
+{
+public:
+ typedef boost::shared_ptr<x300_mb_eeprom_iface> sptr;
+
+ virtual ~x300_mb_eeprom_iface(void) = 0;
+
+ static sptr make(uhd::wb_iface::sptr wb, uhd::i2c_iface::sptr i2c);
+};
+
+#endif /* INCLUDED_X300_MB_EEPROM_HPP */
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index 6e7c47a64..d908bfb34 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -33,6 +33,9 @@ static const int BL_DATA = 1;
#define I2C1_BASE 0xff00
#define SR_ADDR(base, offset) ((base) + (offset)*4)
+//I2C1 device addresses
+#define MBOARD_EEPROM_ADDR 0x50
+
static const int ZPU_SR_LEDS = 00;
static const int ZPU_SR_SW_RST = 01;
static const int ZPU_SR_CLOCK_CTRL = 02;
diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp
index b5f63bcbb..dd04dcafc 100644
--- a/host/tests/convert_test.cpp
+++ b/host/tests/convert_test.cpp
@@ -285,8 +285,8 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){
const size_t nsamps = 13;
std::vector<fc32_t> input(nsamps);
BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
- (std::rand()/float(RAND_MAX/2)) - 1,
- (std::rand()/float(RAND_MAX/2)) - 1
+ (std::rand()/(RAND_MAX/2.0)) - 1,
+ (std::rand()/(RAND_MAX/2.0)) - 1
);
std::vector<uint32_t> interm(nsamps);
std::vector<sc16_t> output(nsamps);
@@ -581,7 +581,7 @@ static void test_convert_types_f32(
){
//fill the input samples
std::vector<float> input(nsamps), output(nsamps);
- BOOST_FOREACH(float &in, input) in = float((std::rand()/float(RAND_MAX/2)) - 1);
+ BOOST_FOREACH(float &in, input) in = float((float(std::rand())/float(RAND_MAX/2)) - 1);
//run the loopback and test
convert::id_type in_id = id;
diff --git a/host/utils/converter_benchmark.cpp b/host/utils/converter_benchmark.cpp
index c0cd28440..f6d7e9650 100644
--- a/host/utils/converter_benchmark.cpp
+++ b/host/utils/converter_benchmark.cpp
@@ -82,8 +82,8 @@ void init_random_vector_complex_float(std::vector<char> &buf_ptr, const size_t n
std::complex<T> * const buf = reinterpret_cast<std::complex<T> * const>(&buf_ptr[0]);
for (size_t i = 0; i < n_items; i++) {
buf[i] = std::complex<T>(
- T((std::rand()/double(RAND_MAX/2)) - 1),
- T((std::rand()/double(RAND_MAX/2)) - 1)
+ T(std::rand()/(RAND_MAX/2.0) - 1),
+ T(std::rand()/(RAND_MAX/2.0) - 1)
);
}
}