diff options
author | Ashish Chaudhari <ashish@ettus.com> | 2016-06-23 16:22:06 -0700 |
---|---|---|
committer | Ashish Chaudhari <ashish@ettus.com> | 2016-07-07 18:37:43 -0700 |
commit | 7cc16e5be09d29495db3e4076330ee66c8eeca24 (patch) | |
tree | 7d83445e4416447372e6852aa8a21daa4de87710 | |
parent | abc4790ae4be6d542ea39c8ce42045c3fec40b9d (diff) | |
download | uhd-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.c | 91 | ||||
-rwxr-xr-x | firmware/usrp3/x300/x300_aurora_bist.py | 211 | ||||
-rwxr-xr-x | firmware/usrp3/x300/x300_debug.py | 8 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_defs.h | 20 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_init.c | 24 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_main.c | 8 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 28 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_regs.hpp | 42 |
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) |