diff options
author | Josh Blum <josh@joshknows.com> | 2011-03-03 19:26:32 -0800 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2011-03-03 19:26:32 -0800 |
commit | d93a2cf7c904964ba7f41f4d654b18e099df7451 (patch) | |
tree | a55f8d56904a8a4f8fe96dbf7c38177b4c662c5c | |
parent | 942c69b710510e6143a6f3c22bbe3ff0687f4bc6 (diff) | |
download | uhd-d93a2cf7c904964ba7f41f4d654b18e099df7451.tar.gz uhd-d93a2cf7c904964ba7f41f4d654b18e099df7451.tar.bz2 uhd-d93a2cf7c904964ba7f41f4d654b18e099df7451.zip |
usrp2: work on mtu discovery
added echo routine to the firmware and discovery routine to host
the implementation is integrated into the factory function and appears to work on linux
-rw-r--r-- | firmware/zpu/apps/txrx_uhd.c | 17 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 6 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 96 |
4 files changed, 108 insertions, 19 deletions
diff --git a/firmware/zpu/apps/txrx_uhd.c b/firmware/zpu/apps/txrx_uhd.c index 0c93d2352..68c24e872 100644 --- a/firmware/zpu/apps/txrx_uhd.c +++ b/firmware/zpu/apps/txrx_uhd.c @@ -203,10 +203,7 @@ static void handle_udp_ctrl_packet( * Peek and Poke Register ******************************************************************/ case USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO: - if (0){//ctrl_data_in->data.poke_args.addr < 0xC000){ - printf("error! tried to poke into 0x%x\n", ctrl_data_in->data.poke_args.addr); - } - else switch(ctrl_data_in->data.poke_args.num_bytes){ + switch(ctrl_data_in->data.poke_args.num_bytes){ case sizeof(uint32_t): *((uint32_t *) ctrl_data_in->data.poke_args.addr) = (uint32_t)ctrl_data_in->data.poke_args.data; break; @@ -241,6 +238,9 @@ static void handle_udp_ctrl_packet( ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE; break; + /******************************************************************* + * UART Control + ******************************************************************/ case USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO:{ //executes a readline()-style read, up to num_bytes long, up to and including newline int num_bytes = ctrl_data_in->data.uart_args.bytes; @@ -263,6 +263,15 @@ static void handle_udp_ctrl_packet( break; } + /******************************************************************* + * Echo test + ******************************************************************/ + case USRP2_CTRL_ID_HOLLER_AT_ME_BRO: + ctrl_data_out.data.echo_args.len = payload_len; + ctrl_data_out.id = USRP2_CTRL_ID_HOLLER_BACK_DUDE; + send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, ctrl_data_in->data.echo_args.len); + return; + default: ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 6eb047454..68c49cafc 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -89,6 +89,9 @@ typedef enum{ USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO = 'v', USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE = 'V', + USRP2_CTRL_ID_HOLLER_AT_ME_BRO = 'l', + USRP2_CTRL_ID_HOLLER_BACK_DUDE = 'L', + USRP2_CTRL_ID_PEACE_OUT = '~' } usrp2_ctrl_id_t; @@ -133,6 +136,9 @@ typedef struct{ uint8_t bytes; uint8_t data[20]; } uart_args; + struct { + uint32_t len; + } echo_args; } data; } usrp2_ctrl_data_t; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 5cb4e4d34..0a6fefca6 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -62,25 +62,25 @@ usrp2_mboard_impl::usrp2_mboard_impl( ): _index(index), _device(device), _iface(usrp2_iface::make(udp_simple::make_connected( - device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT) + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) ))) { //construct transports for dsp and async errors std::cout << "Making transport for DSP0..." << std::endl; device.dsp_xports.push_back(udp_zero_copy::make( - device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_DSP0_PORT), device_addr + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_DSP0_PORT), device_addr )); init_xport(device.dsp_xports.back()); std::cout << "Making transport for DSP1..." << std::endl; device.dsp_xports.push_back(udp_zero_copy::make( - device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_DSP1_PORT), device_addr + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_DSP1_PORT), device_addr )); init_xport(device.dsp_xports.back()); std::cout << "Making transport for ERR0..." << std::endl; device.err_xports.push_back(udp_zero_copy::make( - device_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_ERR0_PORT), device_addr_t() + device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_ERR0_PORT), device_addr_t() )); init_xport(device.err_xports.back()); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 651e9a89b..164253f96 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -143,7 +143,75 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){ /*********************************************************************** * Make **********************************************************************/ -static device::sptr usrp2_make(const device_addr_t &_device_addr){ +static device::sptr usrp2_make(const device_addr_t &device_addr){ + return device::sptr(new usrp2_impl(device_addr)); +} + +UHD_STATIC_BLOCK(register_usrp2_device){ + device::register_device(&usrp2_find, &usrp2_make); +} + +/*********************************************************************** + * MTU Discovery + **********************************************************************/ +struct mtu_result_t{ + size_t recv_mtu, send_mtu; +}; + +static mtu_result_t determine_mtu(const std::string &addr){ + udp_simple::sptr udp_sock = udp_simple::make_connected( + addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) + ); + + mtu_result_t mtu; + boost::uint8_t buffer[2000]; //FIXME use real FPGA buffer maximum + usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(buffer); + static const double echo_timeout = 0.010; //10 ms + + size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = sizeof(buffer); + size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = sizeof(buffer); + + while (min_recv_mtu + 4 < max_recv_mtu){ + + mtu.recv_mtu = (max_recv_mtu + min_recv_mtu)/2 & ~(4-1); + //std::cout << "recv_mtu " << mtu.recv_mtu << std::endl; + + ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO); + ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM); + ctrl_data->data.echo_args.len = htonl(mtu.recv_mtu); + udp_sock->send(boost::asio::buffer(buffer, sizeof(usrp2_ctrl_data_t))); + + size_t len = udp_sock->recv(boost::asio::buffer(buffer), echo_timeout); + + if (len >= mtu.recv_mtu) min_recv_mtu = mtu.recv_mtu; + else max_recv_mtu = mtu.recv_mtu; + + } + + while (min_send_mtu + 4 < max_send_mtu){ + + mtu.send_mtu = (max_send_mtu + min_send_mtu)/2 & ~(4-1); + //std::cout << "send_mtu " << mtu.send_mtu << std::endl; + + ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO); + ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM); + ctrl_data->data.echo_args.len = htonl(sizeof(usrp2_ctrl_data_t)); + udp_sock->send(boost::asio::buffer(buffer, mtu.send_mtu)); + + size_t len = udp_sock->recv(boost::asio::buffer(buffer), echo_timeout); + if (len >= sizeof(usrp2_ctrl_data_t)) len = ntohl(ctrl_data->data.echo_args.len); + + if (len >= mtu.send_mtu) min_send_mtu = mtu.send_mtu; + else max_send_mtu = mtu.send_mtu; + } + + return mtu; +} + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ device_addr_t device_addr = _device_addr; //setup the dsp transport hints (default to a large recv buff) @@ -157,18 +225,24 @@ static device::sptr usrp2_make(const device_addr_t &_device_addr){ #endif } - return device::sptr(new usrp2_impl(device_addr)); -} + device_addrs_t device_args = separate_device_addr(device_addr); -UHD_STATIC_BLOCK(register_usrp2_device){ - device::register_device(&usrp2_find, &usrp2_make); -} + //calculate the minimum send and recv mtu of all devices + mtu_result_t mtu = determine_mtu(device_args[0]["addr"]); + for (size_t i = 1; i < device_args.size(); i++){ + mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]); + mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu); + mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu); + } -/*********************************************************************** - * Structors - **********************************************************************/ -usrp2_impl::usrp2_impl(const device_addr_t &device_addr){ - device_addrs_t device_args = separate_device_addr(device_addr); + std::cout << "mtu recv bytes " << mtu.recv_mtu << std::endl; + std::cout << "mtu send bytes " << mtu.send_mtu << std::endl; + + //use the discovered mtu if not specified by the user + if (not device_addr.has_key("recv_frame_size")) + device_addr["recv_frame_size"] = boost::lexical_cast<std::string>(mtu.recv_mtu); + if (not device_addr.has_key("send_frame_size")) + device_addr["send_frame_size"] = boost::lexical_cast<std::string>(mtu.send_mtu); //setup rx otw type _rx_otw_type.width = 16; |