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)  | 
