aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-03-03 19:26:32 -0800
committerJosh Blum <josh@joshknows.com>2011-03-03 19:26:32 -0800
commitd93a2cf7c904964ba7f41f4d654b18e099df7451 (patch)
treea55f8d56904a8a4f8fe96dbf7c38177b4c662c5c
parent942c69b710510e6143a6f3c22bbe3ff0687f4bc6 (diff)
downloaduhd-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.c17
-rw-r--r--host/lib/usrp/usrp2/fw_common.h6
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp8
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp96
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;