aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2016-06-23 16:22:06 -0700
committerAshish Chaudhari <ashish@ettus.com>2016-07-07 18:37:43 -0700
commit7cc16e5be09d29495db3e4076330ee66c8eeca24 (patch)
tree7d83445e4416447372e6852aa8a21daa4de87710
parentabc4790ae4be6d542ea39c8ce42045c3fec40b9d (diff)
downloaduhd-7cc16e5be09d29495db3e4076330ee66c8eeca24.tar.gz
uhd-7cc16e5be09d29495db3e4076330ee66c8eeca24.tar.bz2
uhd-7cc16e5be09d29495db3e4076330ee66c8eeca24.zip
x300: UHD is now compatible with FPGA images with Aurora support
- UHD and ZPU is now aware of Aurora SFP+ transceivers in the FPGA image - Added script to exercise Aurora BIST features
-rw-r--r--firmware/usrp3/lib/ethernet.c91
-rwxr-xr-xfirmware/usrp3/x300/x300_aurora_bist.py211
-rwxr-xr-xfirmware/usrp3/x300/x300_debug.py8
-rw-r--r--firmware/usrp3/x300/x300_defs.h20
-rw-r--r--firmware/usrp3/x300/x300_init.c24
-rw-r--r--firmware/usrp3/x300/x300_main.c8
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp28
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp42
8 files changed, 342 insertions, 90 deletions
diff --git a/firmware/usrp3/lib/ethernet.c b/firmware/usrp3/lib/ethernet.c
index e9c18528d..e5226489f 100644
--- a/firmware/usrp3/lib/ethernet.c
+++ b/firmware/usrp3/lib/ethernet.c
@@ -161,8 +161,8 @@ ge_write_mdio(const uint32_t base, const uint32_t address, const uint32_t port,
static uint32_t read_mdio(const uint8_t eth, const uint32_t address, const uint32_t device, const uint32_t port)
{
- const uint32_t rb_addr = (eth==0) ? RB_ETH_TYPE0 : RB_ETH_TYPE1;
- const uint32_t base = (eth==0) ? XGE0_BASE : XGE1_BASE;
+ const uint32_t rb_addr = (eth==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE;
+ const uint32_t base = (eth==0) ? SFP0_MAC_BASE : SFP1_MAC_BASE;
if (wb_peek32(SR_ADDR(RB0_BASE, rb_addr)) != 0)
{
return xge_read_mdio(base, address, device, port);
@@ -175,8 +175,8 @@ static uint32_t read_mdio(const uint8_t eth, const uint32_t address, const uint3
static void write_mdio(const uint8_t eth, const uint32_t address, const uint32_t device, const uint32_t port, const uint32_t data)
{
- const uint32_t rb_addr = (eth==0) ? RB_ETH_TYPE0 : RB_ETH_TYPE1;
- const uint32_t base = (eth==0) ? XGE0_BASE : XGE1_BASE;
+ const uint32_t rb_addr = (eth==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE;
+ const uint32_t base = (eth==0) ? SFP0_MAC_BASE : SFP1_MAC_BASE;
if (wb_peek32(SR_ADDR(RB0_BASE, rb_addr)) != 0)
{
return xge_write_mdio(base, address, device, port, data);
@@ -329,18 +329,17 @@ static void xge_phy_init(const uint8_t eth, const uint32_t mdio_port)
}
}
-void update_eth_state(const uint32_t eth)
+void update_eth_state(const uint32_t eth, const uint32_t sfp_type)
{
const bool old_link_up = links_up[eth];
- const uint32_t status_reg_addr = (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1;
- const bool is_10g = (wb_peek32(SR_ADDR(RB0_BASE, eth == 0 ? RB_ETH_TYPE0 : RB_ETH_TYPE1)) == 1);
+ const uint32_t status_reg_addr = (eth==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS;
uint32_t sfpp_status = wb_peek32(SR_ADDR(RB0_BASE, status_reg_addr)) & 0xFFFF;
if ((sfpp_status & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0) {
//SFP+ pin state changed. Reinitialize PHY and MAC
- if (is_10g) {
- xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE);
- xge_phy_init(eth ,MDIO_PORT);
+ if (sfp_type == RB_SFP_10G_ETH) {
+ xge_mac_init((eth==0) ? SFP0_MAC_BASE : SFP1_MAC_BASE);
+ xge_phy_init(eth, MDIO_PORT);
} else {
//No-op for 1G
}
@@ -348,7 +347,7 @@ void update_eth_state(const uint32_t eth)
int8_t timeout = 100;
bool link_up = false;
do {
- if (is_10g) {
+ if (sfp_type == RB_SFP_10G_ETH) {
link_up = ((read_mdio(eth, XGE_MDIO_STATUS1,XGE_MDIO_DEVICE_PMA,MDIO_PORT)) & (1 << 2)) != 0;
} else {
link_up = ((wb_peek32(SR_ADDR(RB0_BASE, status_reg_addr)) >> 16) & 0x1) != 0;
@@ -363,54 +362,66 @@ void update_eth_state(const uint32_t eth)
}
if (!old_link_up && links_up[eth]) u3_net_stack_send_arp_request(eth, u3_net_stack_get_ip_addr(eth));
- UHD_FW_TRACE_FSTR(INFO, "The link on eth port %u is %s", eth, links_up[eth]?"up":"down");
}
-void poll_sfpp_status(const uint32_t eth)
+void poll_sfpp_status(const uint32_t sfp)
{
- uint32_t x;
- // Has MODDET/MODAbS changed since we last looked?
- x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
+ uint32_t type = wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE));
+ uint32_t status = wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS));
- if (x & SFPP_STATUS_RXLOS_CHG)
- UHD_FW_TRACE_FSTR(DEBUG, "eth%1d RXLOS changed state: %d", eth, (x & SFPP_STATUS_RXLOS));
- if (x & SFPP_STATUS_TXFAULT_CHG)
- UHD_FW_TRACE_FSTR(DEBUG, "eth%1d TXFAULT changed state: %d", eth, ((x & SFPP_STATUS_TXFAULT) >> 1));
- if (x & SFPP_STATUS_MODABS_CHG)
- UHD_FW_TRACE_FSTR(DEBUG, "eth%1d MODABS changed state: %d", eth, ((x & SFPP_STATUS_MODABS) >> 2));
-
- //update the link up status
- if ((x & SFPP_STATUS_RXLOS_CHG) || (x & SFPP_STATUS_TXFAULT_CHG) || (x & SFPP_STATUS_MODABS_CHG))
- {
- update_eth_state(eth);
- }
-
- if (x & SFPP_STATUS_MODABS_CHG) {
+ if (status & SFPP_STATUS_MODABS_CHG) {
// MODDET has changed state since last checked
- if (x & SFPP_STATUS_MODABS) {
+ if (status & SFPP_STATUS_MODABS) {
// MODDET is high, module currently removed.
- UHD_FW_TRACE_FSTR(INFO, "An SFP+ module has been removed from eth port %d.", eth);
+ UHD_FW_TRACE_FSTR(INFO, "An SFP+ module has been removed from eth port %d.", sfp);
} else {
// MODDET is low, module currently inserted.
// Return status.
- UHD_FW_TRACE_FSTR(INFO, "A new SFP+ module has been inserted into eth port %d.", eth);
- xge_read_sfpp_type((eth==0) ? I2C0_BASE : I2C2_BASE,1);
+ UHD_FW_TRACE_FSTR(INFO, "A new SFP+ module has been inserted into eth port %d.", sfp);
+ if (type == RB_SFP_10G_ETH) {
+ xge_read_sfpp_type((sfp==0) ? I2C0_BASE : I2C2_BASE,1);
+ }
}
}
+
+ if (status & SFPP_STATUS_RXLOS_CHG) {
+ UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d RXLOS changed state: %d", sfp, (status & SFPP_STATUS_RXLOS));
+ }
+ if (status & SFPP_STATUS_TXFAULT_CHG) {
+ UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d TXFAULT changed state: %d", sfp, ((status & SFPP_STATUS_TXFAULT) >> 1));
+ }
+ if (status & SFPP_STATUS_MODABS_CHG) {
+ UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d MODABS changed state: %d", sfp, ((status & SFPP_STATUS_MODABS) >> 2));
+ }
+
+ //update the link up status
+ const bool old_link_up = links_up[sfp];
+ if (type == RB_SFP_AURORA) {
+ links_up[sfp] = ((wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS)) >> 16) & 0x1) != 0;
+ } else {
+ if ((status & SFPP_STATUS_RXLOS_CHG) ||
+ (status & SFPP_STATUS_TXFAULT_CHG) ||
+ (status & SFPP_STATUS_MODABS_CHG))
+ {
+ update_eth_state(sfp, type);
+ }
+ }
+ if (old_link_up != links_up[sfp]) {
+ UHD_FW_TRACE_FSTR(INFO, "The link on SFP port %u is %s", sfp, links_up[sfp]?"up":"down");
+ }
}
-void ethernet_init(const uint32_t eth)
+void ethernet_init(const uint32_t sfp)
{
#ifdef UHD_FW_TRACE_LEVEL
- uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
- UHD_FW_TRACE_FSTR(DEBUG, "eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d",
- eth,
+ uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_STATUS : RB_SFP1_STATUS ));
+ UHD_FW_TRACE_FSTR(DEBUG, "SFP%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d",
+ sfp,
(x & SFPP_STATUS_RXLOS),
((x & SFPP_STATUS_TXFAULT) >> 1),
((x & SFPP_STATUS_MODABS) >> 2));
#endif
- links_up[eth] = false;
- update_eth_state(eth);
+ update_eth_state(sfp, wb_peek32(SR_ADDR(RB0_BASE, (sfp==0) ? RB_SFP0_TYPE : RB_SFP1_TYPE)));
}
//
diff --git a/firmware/usrp3/x300/x300_aurora_bist.py b/firmware/usrp3/x300/x300_aurora_bist.py
new file mode 100755
index 000000000..1cfbd89c3
--- /dev/null
+++ b/firmware/usrp3/x300/x300_aurora_bist.py
@@ -0,0 +1,211 @@
+#!/usr/bin/env python
+#
+# 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/>.
+#
+
+import x300_debug
+import optparse
+import time
+import datetime
+import math
+import tqdm
+
+########################################################################
+# constants
+########################################################################
+SFP0_MAC_REG_BASE = 0xC000
+SFP1_MAC_REG_BASE = 0xD000
+SFP0_TYPE_REG_OFFSET = 0xA000 + 16
+SFP1_TYPE_REG_OFFSET = 0xA000 + 20
+SFP0_STATUS_REG_OFFSET = 0xA000 + 32
+SFP1_STATUS_REG_OFFSET = 0xA000 + 36
+
+SFP_TYPE_AURORA = 2
+
+MAC_REG_CTRL = 0
+MAC_REG_STATUS = 0
+MAC_REG_OVERRUNS = 4
+MAC_REG_BIST_SAMPS = 8
+MAC_REG_BIST_ERRORS = 12
+
+MAC_STATUS_LINK_UP_MSK = 0x00000001
+MAC_STATUS_HARD_ERR_MSK = 0x00000002
+MAC_STATUS_SOFT_ERR_MSK = 0x00000004
+MAC_STATUS_BIST_LOCKED_MSK = 0x00000008
+MAC_STATUS_BIST_LATENCY_MSK = 0x000FFFF0
+MAC_STATUS_BIST_LATENCY_OFFSET = 4
+MAC_STATUS_CHECKSUM_ERRS_MSK = 0xFFF00000
+MAC_STATUS_CHECKSUM_ERRS_OFFSET = 20
+
+MAC_CTRL_BIST_CHECKER_EN = 0x00000001
+MAC_CTRL_BIST_GEN_EN = 0x00000002
+MAC_CTRL_BIST_LOOPBACK_EN = 0x00000004
+MAC_CTRL_PHY_RESET = 0x00000100
+MAC_CTRL_BIST_RATE_MSK = 0x000000F8
+MAC_CTRL_BIST_RATE_OFFSET = 3
+
+AURORA_CLK_RATE = 156.25e6
+BUS_CLK_RATE = 166.66e6
+BIST_MAX_TIME_LIMIT = math.floor(pow(2,48)/AURORA_CLK_RATE)-1
+
+########################################################################
+# utils
+########################################################################
+def get_aurora_info(ctrl):
+ if (ctrl.peek(SFP0_TYPE_REG_OFFSET) == SFP_TYPE_AURORA):
+ aur_port = 0
+ elif (ctrl.peek(SFP1_TYPE_REG_OFFSET) == SFP_TYPE_AURORA):
+ aur_port = 1
+ else:
+ aur_port = -1
+ link_up = False
+ if aur_port != -1:
+ mac_base = SFP0_MAC_REG_BASE if aur_port == 0 else SFP1_MAC_REG_BASE
+ link_up = ((ctrl.peek(mac_base + MAC_REG_STATUS) & MAC_STATUS_LINK_UP_MSK) != 0)
+ return (aur_port, link_up)
+
+def get_rate_setting(rate):
+ for div in range(2,32):
+ if (rate < 8e-6 * BUS_CLK_RATE * (1.0 - 1.0/div)):
+ return (div-1, 8e-6 * BUS_CLK_RATE * (1.0 - 1.0/(div-1)))
+ return (0, 8e-6 * BUS_CLK_RATE)
+
+def run_loopback_bist(ctrls, duration, (rate_sett, rate)):
+ print '[INFO] Running Loopback BIST at %.0fMB/s for %.0fs...'%(rate,duration)
+ # Determine offsets
+ (mst_port, link_up) = get_aurora_info(ctrls['master'])
+ MST_MAC_REG_BASE = SFP0_MAC_REG_BASE if (mst_port == 0) else SFP1_MAC_REG_BASE
+ if 'slave' in ctrls:
+ (sla_port, link_up) = get_aurora_info(ctrls['slave'])
+ SLA_MAC_REG_BASE = SFP0_MAC_REG_BASE if (sla_port == 0) else SFP1_MAC_REG_BASE
+ # Reset both PHYS
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_PHY_RESET)
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_PHY_RESET)
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ time.sleep(1.5)
+ # Put the slave in loopback mode and the master in BIST mode
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_LOOPBACK_EN)
+ if rate_sett == 0:
+ master_ctrl = MAC_CTRL_BIST_GEN_EN|MAC_CTRL_BIST_CHECKER_EN
+ else:
+ master_ctrl = ((rate_sett - 1) << MAC_CTRL_BIST_RATE_OFFSET)|MAC_CTRL_BIST_GEN_EN|MAC_CTRL_BIST_CHECKER_EN
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, master_ctrl)
+ start_time = datetime.datetime.now()
+ # Wait and check if BIST locked
+ time.sleep(0.5)
+ mst_status = ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_STATUS)
+ if (not (mst_status & MAC_STATUS_BIST_LOCKED_MSK)):
+ print '[ERROR] BIST engine did not lock onto a PRBS word!'
+ # Wait for requested time
+ try:
+ for i in tqdm.tqdm(range(duration), desc='[INFO] Progress'):
+ time.sleep(1.0)
+ except KeyboardInterrupt:
+ print '[WARNING] Operation cancelled by user.'
+ # Turn off the BIST generator and loopback
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ stop_time = datetime.datetime.now()
+ time.sleep(0.5)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ # Validate status and no overruns
+ mst_status = ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_STATUS)
+ mst_overruns = ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_OVERRUNS)
+ if (mst_status & MAC_STATUS_HARD_ERR_MSK):
+ print '[ERROR] Hard errors in master PHY'
+ if (mst_overruns > 0):
+ print '[ERROR] Buffer overruns in master PHY'
+ if 'slave' in ctrls:
+ sla_status = ctrls['slave'].peek(SLA_MAC_REG_BASE + MAC_REG_STATUS)
+ sla_overruns = ctrls['slave'].peek(SLA_MAC_REG_BASE + MAC_REG_OVERRUNS)
+ if (sla_status & MAC_STATUS_HARD_ERR_MSK):
+ print '[ERROR] Hard errors in slave PHY'
+ if (sla_overruns > 0):
+ print '[ERROR] Buffer overruns in slave PHY'
+ # Compure latency
+ mst_samps = 65536.0*ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_BIST_SAMPS)
+ mst_errors = 1.0*ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_BIST_ERRORS)
+ if (mst_samps != 0):
+ mst_latency_cyc = 16.0*((mst_status & MAC_STATUS_BIST_LATENCY_MSK) >> MAC_STATUS_BIST_LATENCY_OFFSET)
+ time_diff = stop_time - start_time
+ print '[INFO] BIST Complete!'
+ print '- Elapsed Time = ' + str(time_diff)
+ print '- Max BER (Bit Error Ratio) = %.4g (%d errors out of %d)'%((mst_errors+1)/mst_samps,mst_errors,mst_samps)
+ print '- Max Roundtrip Latency = %.1fus'%(1e6*mst_latency_cyc/AURORA_CLK_RATE)
+ print '- Approx Throughput = %.0fMB/s'%((8e-6*mst_samps)/time_diff.total_seconds())
+ else:
+ print '[ERROR] BIST Failed!'
+ # Drain and Cleanup
+ print '[INFO] Cleaning up...'
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ time.sleep(0.5)
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+
+########################################################################
+# command line options
+########################################################################
+def get_options():
+ parser = optparse.OptionParser()
+ parser.add_option("--master", type="string", help="IP Address of master USRP-X3X0 device", default=None)
+ parser.add_option("--slave", type="string", help="IP Address of slave USRP-X3X0 device", default=None)
+ parser.add_option("--duration", type="int", help="Duration of test in seconds", default=10)
+ parser.add_option("--rate", type="int", help="BIST throughput in MB/s", default=1245)
+ (options, args) = parser.parse_args()
+ return options
+
+########################################################################
+# main
+########################################################################
+if __name__=='__main__':
+ options = get_options()
+
+ if not options.master: raise Exception('No master address specified')
+ if (options.duration < 0 or options.duration > BIST_MAX_TIME_LIMIT):
+ raise Exception('Invalid duration. Min = 0s and Max = %ds'%(BIST_MAX_TIME_LIMIT))
+
+ ctrls = dict()
+ ctrls['master'] = x300_debug.ctrl_socket(addr=options.master)
+ if options.slave:
+ ctrls['slave'] = x300_debug.ctrl_socket(addr=options.slave)
+
+ # Report device and core info
+ links_up = True
+ for node in ctrls:
+ print '[INFO] ' + node.upper() + ':'
+ ctrl = ctrls[node]
+ (aur_port, link_up) = get_aurora_info(ctrl)
+ if aur_port >= 0:
+ status_str = str(aur_port) + (' UP' if link_up else ' DOWN')
+ else:
+ status_str = 'Not Detected!'
+ print '- Mgmt IP Addr : ' + (options.master if node == 'master' else options.slave)
+ print '- Aurora Status : Port ' + status_str
+ links_up = links_up & link_up
+
+ # Sanity check
+ if not links_up:
+ print '[ERROR] At least one of the links is down. Cannot proceed.'
+ exit(1)
+
+ # Run BIST
+ run_loopback_bist(ctrls, options.duration, get_rate_setting(options.rate))
diff --git a/firmware/usrp3/x300/x300_debug.py b/firmware/usrp3/x300/x300_debug.py
index 1596929ad..f5dfad7f6 100755
--- a/firmware/usrp3/x300/x300_debug.py
+++ b/firmware/usrp3/x300/x300_debug.py
@@ -110,7 +110,7 @@ class ctrl_socket(object):
(flags, rxseq, addr, data) = unpack_reg_peek_poke_fmt(in_pkt)
if flags & X300_FW_COMMS_FLAGS_ERROR == X300_FW_COMMS_FLAGS_ERROR:
raise Exception("X300 peek of address %d returns error code" % (addr))
- print("PEEK of address %d(0x%x) reads %d(0x%x)" % (addr,addr,data,data))
+ return data
def poke(self,poke_addr,poke_data):
out_pkt = pack_reg_peek_poke_fmt(X300_FW_COMMS_FLAGS_POKE32|X300_FW_COMMS_FLAGS_ACK, seq(), poke_addr, poke_data)
@@ -118,7 +118,6 @@ class ctrl_socket(object):
(flags, rxseq, addr, data) = unpack_reg_peek_poke_fmt(in_pkt)
if flags & X300_FW_COMMS_FLAGS_ERROR == X300_FW_COMMS_FLAGS_ERROR:
raise Exception("X300 peek of address %d returns error code" % (addr))
- print("POKE of address %d(0x%x) with %d(0x%x)" % (poke_addr,poke_addr,poke_data,poke_data) )
########################################################################
@@ -159,9 +158,12 @@ if __name__=='__main__':
if options.peek is not None:
addr = options.peek
- status.peek(addr)
+ data = status.peek(addr)
+ print("PEEK of address %d(0x%x) reads %d(0x%x)" % (addr,addr,data,data))
if options.poke is not None and options.data is not None:
addr = options.poke
data = options.data
status.poke(addr,data)
+ print("POKE of address %d(0x%x) with %d(0x%x)" % (addr,addr,data,data))
+
diff --git a/firmware/usrp3/x300/x300_defs.h b/firmware/usrp3/x300/x300_defs.h
index c4011bd12..cb8b7324f 100644
--- a/firmware/usrp3/x300/x300_defs.h
+++ b/firmware/usrp3/x300/x300_defs.h
@@ -7,8 +7,8 @@
#define CPU_CLOCK 166666667
#define MAIN_RAM_BASE 0x0000
#define PKT_RAM0_BASE 0x8000
-#define XGE0_BASE 0xC000
-#define XGE1_BASE 0xD000
+#define SFP0_MAC_BASE 0xC000
+#define SFP1_MAC_BASE 0xD000
#define BOOT_LDR_BASE 0xFC00
#define UART0_BASE 0xfd00
#define UART0_BAUD 115200
@@ -21,9 +21,6 @@
#define RB0_BASE 0xa000 //same as set
#define SETXB_BASE 0xb000
-#define ETH1G
-//#define ETH10G
-
//eeprom map for mboard addrs
#define MBOARD_EEPROM_ADDR 0x50
@@ -49,11 +46,11 @@ static const int LED_LINKACT = (1 << 0);
static const int RB_COUNTER = 0;
static const int RB_SPI_RDY = 1;
static const int RB_SPI_DATA = 2;
-static const int RB_ETH_TYPE0 = 4;
-static const int RB_ETH_TYPE1 = 5;
+static const int RB_SFP0_TYPE = 4;
+static const int RB_SFP1_TYPE = 5;
static const int RB_FPGA_COMPAT = 6;
-static const int RB_SFPP_STATUS0 = 8;
-static const int RB_SFPP_STATUS1 = 9;
+static const int RB_SFP0_STATUS = 8;
+static const int RB_SFP1_STATUS = 9;
// Bootloader Memory Map
static const int BL_ADDRESS = 0;
@@ -73,4 +70,9 @@ static const int BL_DATA = 1;
#define ETH_FRAMER_DST_UDP_MAC 6
#define ETH_FRAMER_DST_MAC_LO 7
+// SFP type constants
+#define RB_SFP_1G_ETH 0
+#define RB_SFP_10G_ETH 1
+#define RB_SFP_AURORA 2
+
#endif /* INCLUDED_X300_DEFS_H */
diff --git a/firmware/usrp3/x300/x300_init.c b/firmware/usrp3/x300/x300_init.c
index 97b20032b..57c1faa2c 100644
--- a/firmware/usrp3/x300/x300_init.c
+++ b/firmware/usrp3/x300/x300_init.c
@@ -84,8 +84,8 @@ static void init_network(void)
wb_i2c_read(I2C1_BASE, MBOARD_EEPROM_ADDR, (uint8_t *)(&eeprom_map), sizeof(eeprom_map));
//determine interface number
- const size_t eth0no = wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE0))? 2 : 0;
- const size_t eth1no = wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE1))? 3 : 1;
+ 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);
@@ -159,15 +159,19 @@ void x300_init(void)
wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), 0);
//print network summary
- for (uint8_t e = 0; e < ethernet_ninterfaces(); e++)
+ for (uint8_t sfp = 0; sfp < ethernet_ninterfaces(); sfp++)
{
- uint32_t offset = SR_ADDR(RB0_BASE, ((e==1)?RB_ETH_TYPE1:RB_ETH_TYPE0));
- UHD_FW_TRACE_FSTR(INFO, "Ethernet Port %u:", (int)e);
- UHD_FW_TRACE_FSTR(INFO, "-- PHY: %s", ((wb_peek32(offset)==1) ? "10Gbps" : "1Gbps"));
- UHD_FW_TRACE_FSTR(INFO, "-- MAC: %s", mac_addr_to_str(u3_net_stack_get_mac_addr(e)));
- UHD_FW_TRACE_FSTR(INFO, "-- IP: %s", ip_addr_to_str(u3_net_stack_get_ip_addr(e)));
- UHD_FW_TRACE_FSTR(INFO, "-- SUBNET: %s", ip_addr_to_str(u3_net_stack_get_subnet(e)));
- UHD_FW_TRACE_FSTR(INFO, "-- BCAST: %s", ip_addr_to_str(u3_net_stack_get_bcast(e)));
+ uint32_t sfp_type = wb_peek32(SR_ADDR(RB0_BASE, ((sfp==1) ? RB_SFP1_TYPE : RB_SFP0_TYPE)));
+ UHD_FW_TRACE_FSTR(INFO, "SFP+ Port %u:", (int)sfp);
+ if (sfp_type == RB_SFP_AURORA) {
+ UHD_FW_TRACE (INFO, "-- PHY: 10Gbps Aurora");
+ } else {
+ UHD_FW_TRACE_FSTR(INFO, "-- PHY: %s", (sfp_type == RB_SFP_10G_ETH) ? "10Gbps Ethernet" : "1Gbps Ethernet");
+ UHD_FW_TRACE_FSTR(INFO, "-- MAC: %s", mac_addr_to_str(u3_net_stack_get_mac_addr(sfp)));
+ UHD_FW_TRACE_FSTR(INFO, "-- IP: %s", ip_addr_to_str(u3_net_stack_get_ip_addr(sfp)));
+ UHD_FW_TRACE_FSTR(INFO, "-- SUBNET: %s", ip_addr_to_str(u3_net_stack_get_subnet(sfp)));
+ UHD_FW_TRACE_FSTR(INFO, "-- BCAST: %s", ip_addr_to_str(u3_net_stack_get_bcast(sfp)));
+ }
}
// For eth interfaces, initialize the PHY's
diff --git a/firmware/usrp3/x300/x300_main.c b/firmware/usrp3/x300/x300_main.c
index 44ed10aa8..eca0802be 100644
--- a/firmware/usrp3/x300/x300_main.c
+++ b/firmware/usrp3/x300/x300_main.c
@@ -320,8 +320,10 @@ static void garp(void)
count = 0;
for (size_t e = 0; e < ethernet_ninterfaces(); e++)
{
- if (!ethernet_get_link_up(e)) continue;
- u3_net_stack_send_arp_request(e, u3_net_stack_get_ip_addr(e));
+ if (wb_peek32(SR_ADDR(RB0_BASE, e == 0 ? RB_SFP0_TYPE : RB_SFP1_TYPE)) != RB_SFP_AURORA) {
+ if (!ethernet_get_link_up(e)) continue;
+ u3_net_stack_send_arp_request(e, u3_net_stack_get_ip_addr(e));
+ }
}
}
@@ -446,7 +448,7 @@ int main(void)
{
poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events.
poll_sfpp_status(1); // Every so often poll XGE Phy to look for SFP+ hotplug events.
- handle_link_state(); //deal with router table update
+ //handle_link_state(); //deal with router table update
handle_claim(); //deal with the host claim register
update_leds(); //run the link and activity leds
garp(); //send periodic garps
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 2a1e77611..2fb7df954 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -65,12 +65,25 @@ static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) {
//Possible options:
//1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ DRAM
//1GS = {0:1G, 1:1G} w/ SRAM, HGS = {0:1G, 1:10G} w/ SRAM, XGS = {0:10G, 1:10G} w/ SRAM
+ //HA = {0:1G, 1:Aurora} w/ DRAM, XA = {0:10G, 1:Aurora} w/ DRAM
std::string option;
- bool eth0XG = (zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_ETH_TYPE0)) == 0x1);
- bool eth1XG = (zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_ETH_TYPE1)) == 0x1);
- option = (eth0XG && eth1XG) ? "XG" : (eth1XG ? "HG" : "1G");
-
+ uint32_t sfp0_type = zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_SFP0_TYPE));
+ uint32_t sfp1_type = zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_SFP1_TYPE));
+
+ if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_1G_ETH) {
+ option = "1G";
+ } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_10G_ETH) {
+ option = "HG";
+ } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_10G_ETH) {
+ option = "XG";
+ } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_AURORA) {
+ option = "HA";
+ } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_AURORA) {
+ option = "XA";
+ } else {
+ option = "HG"; //Default
+ }
if (not has_dram_buff(zpu_ctrl)) {
option += "S";
}
@@ -1356,11 +1369,16 @@ x300_impl::both_xports_t x300_impl::make_transport(
max_link_rate += X300_MAX_RATE_10GIGE;
}
_tree->access<double>(mboard_path).set(max_link_rate);
- } else if (mb.loaded_fpga_image.substr(0,2) == "XG") {
+ } else if (mb.loaded_fpga_image.substr(0,2) == "XG" or mb.loaded_fpga_image.substr(0,2) == "XA") {
eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
size_t max_link_rate = X300_MAX_RATE_10GIGE;
max_link_rate *= mb.eth_conns.size();
_tree->access<double>(mboard_path).set(max_link_rate);
+ } else if (mb.loaded_fpga_image.substr(0,2) == "HA") {
+ eth_data_rec_frame_size = X300_1GE_DATA_FRAME_MAX_SIZE;
+ size_t max_link_rate = X300_MAX_RATE_1GIGE;
+ max_link_rate *= mb.eth_conns.size();
+ _tree->access<double>(mboard_path).set(max_link_rate);
}
if (eth_data_rec_frame_size == 0) {
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index de3a3161a..69a8d5d9f 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -57,10 +57,8 @@ static const uint32_t RB32_MISC_INS = 36;
}}} // namespace
-#define localparam static const int
-
-localparam BL_ADDRESS = 0;
-localparam BL_DATA = 1;
+static const int BL_ADDRESS = 0;
+static const int BL_DATA = 1;
//wishbone settings map - relevant to host code
#define SET0_BASE 0xa000
@@ -70,15 +68,15 @@ localparam BL_DATA = 1;
#define I2C1_BASE 0xff00
#define SR_ADDR(base, offset) ((base) + (offset)*4)
-localparam ZPU_SR_LEDS = 00;
-localparam ZPU_SR_SW_RST = 01;
-localparam ZPU_SR_CLOCK_CTRL = 02;
-localparam ZPU_SR_XB_LOCAL = 03;
-localparam ZPU_SR_SPI = 32;
-localparam ZPU_SR_ETHINT0 = 40;
-localparam ZPU_SR_ETHINT1 = 56;
-localparam ZPU_SR_DRAM_FIFO0 = 72;
-localparam ZPU_SR_DRAM_FIFO1 = 80;
+static const int ZPU_SR_LEDS = 00;
+static const int ZPU_SR_SW_RST = 01;
+static const int ZPU_SR_CLOCK_CTRL = 02;
+static const int ZPU_SR_XB_LOCAL = 03;
+static const int ZPU_SR_SPI = 32;
+static const int ZPU_SR_ETHINT0 = 40;
+static const int ZPU_SR_ETHINT1 = 56;
+static const int ZPU_SR_DRAM_FIFO0 = 72;
+static const int ZPU_SR_DRAM_FIFO1 = 80;
//reset bits
#define ZPU_SR_SW_RST_ETH_PHY (1<<0)
@@ -86,13 +84,17 @@ localparam ZPU_SR_DRAM_FIFO1 = 80;
#define ZPU_SR_SW_RST_RADIO_CLK_PLL (1<<2)
#define ZPU_SR_SW_RST_ADC_IDELAYCTRL (1<<3)
-localparam ZPU_RB_SPI = 2;
-localparam ZPU_RB_CLK_STATUS = 3;
-localparam ZPU_RB_COMPAT_NUM = 6;
-localparam ZPU_RB_ETH_TYPE0 = 4;
-localparam ZPU_RB_ETH_TYPE1 = 5;
-localparam ZPU_RB_DRAM_FIFO0 = 10;
-localparam ZPU_RB_DRAM_FIFO1 = 11;
+static const int ZPU_RB_SPI = 2;
+static const int ZPU_RB_CLK_STATUS = 3;
+static const int ZPU_RB_COMPAT_NUM = 6;
+static const int ZPU_RB_SFP0_TYPE = 4;
+static const int ZPU_RB_SFP1_TYPE = 5;
+static const int ZPU_RB_DRAM_FIFO0 = 10;
+static const int ZPU_RB_DRAM_FIFO1 = 11;
+
+static const uint32_t RB_SFP_1G_ETH = 0;
+static const uint32_t RB_SFP_10G_ETH = 1;
+static const uint32_t RB_SFP_AURORA = 2;
//spi slaves on radio
#define DB_DAC_SEN (1 << 7)