aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Balister <philip@opensdr.com>2011-02-21 04:22:10 -0800
committerPhilip Balister <philip@opensdr.com>2011-02-21 04:22:10 -0800
commit9563275e85d794e66d0aed4fb1c446d3a20b1615 (patch)
tree4d2d10ae728d7dd1303e6d2466d0f2a8518ae238
parent7a786b4eca75ba844a8c79798a5b245b445527da (diff)
parent4787c77bb089bf50a47207bbad55bd65a44769e4 (diff)
downloaduhd-9563275e85d794e66d0aed4fb1c446d3a20b1615.tar.gz
uhd-9563275e85d794e66d0aed4fb1c446d3a20b1615.tar.bz2
uhd-9563275e85d794e66d0aed4fb1c446d3a20b1615.zip
Merge branch 'next' of ettus.sourcerepo.com:ettus/uhdpriv into next
-rw-r--r--host/docs/transport.rst16
-rw-r--r--host/lib/convert/CMakeLists.txt5
-rw-r--r--host/lib/transport/CMakeLists.txt11
-rw-r--r--host/lib/transport/udp_common.hpp53
-rw-r--r--host/lib/transport/udp_simple.cpp160
-rw-r--r--host/lib/transport/udp_zero_copy.cpp (renamed from host/lib/transport/udp_zero_copy_asio.cpp)41
-rw-r--r--host/lib/types/CMakeLists.txt15
-rw-r--r--host/lib/types/time_spec.cpp16
-rw-r--r--host/lib/utils/CMakeLists.txt18
-rwxr-xr-xhost/utils/usrp_n2xx_net_burner.py451
10 files changed, 379 insertions, 407 deletions
diff --git a/host/docs/transport.rst b/host/docs/transport.rst
index 6b9d28bfa..2371d2497 100644
--- a/host/docs/transport.rst
+++ b/host/docs/transport.rst
@@ -17,13 +17,9 @@ that are known to perform well on a variety of systems.
The transport parameters are defined below for the various transports in the UHD:
------------------------------------------------------------------------
-UDP transport (ASIO)
+UDP transport (sockets)
------------------------------------------------------------------------
-The UDP transport is implemented with Boost's ASIO library.
-ASIO provides an asynchronous API for user-space sockets.
-The transport implementation allocates a number of buffers
-and submits asynchronous requests for send and receive.
-IO service threads run in the background to process these requests.
+The UDP transport is implemented with standard user-space/Berkeley sockets.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Transport parameters
@@ -35,8 +31,12 @@ The following parameters can be used to alter the transport's default behavior:
* **send_frame_size:** The size of a single send buffer in bytes
* **num_send_frames:** The number of send buffers to allocate
-**Note:** num_recv_frames and num_send_frames will not have an effect
-as the asynchronous send implementation is currently unimplemented.
+**Note1:** num_recv_frames and num_send_frames do not affect performance.
+
+**Note2:** recv_frame_size and send_frame_size can be used to
+increase or decrease the maximum number of samples per packet.
+The frame sizes default to an MTU of 1472 bytes per IP/UDP packet,
+and may be increased if permitted by your network hardware.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Flow control parameters
diff --git a/host/lib/convert/CMakeLists.txt b/host/lib/convert/CMakeLists.txt
index de9c660e1..abc9c2707 100644
--- a/host/lib/convert/CMakeLists.txt
+++ b/host/lib/convert/CMakeLists.txt
@@ -35,7 +35,10 @@ CHECK_INCLUDE_FILE_CXX(emmintrin.h HAVE_EMMINTRIN_H)
UNSET(CMAKE_REQUIRED_FLAGS)
IF(HAVE_EMMINTRIN_H)
- ADD_DEFINITIONS(${EMMINTRIN_FLAGS})
+ SET_SOURCE_FILES_PROPERTIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/convert_with_sse2.cpp
+ PROPERTIES COMPILE_FLAGS ${EMMINTRIN_FLAGS}
+ )
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/convert_with_sse2.cpp
)
diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt
index a66a58d32..e58957154 100644
--- a/host/lib/transport/CMakeLists.txt
+++ b/host/lib/transport/CMakeLists.txt
@@ -55,14 +55,19 @@ CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H)
IF(HAVE_IFADDRS_H)
MESSAGE(STATUS " Interface address discovery supported through getifaddrs.")
- ADD_DEFINITIONS(-DHAVE_IFADDRS_H)
+ SET(IF_ADDRS_DEFS HAVE_IFADDRS_H)
ELSEIF(HAVE_WINSOCK2_H)
MESSAGE(STATUS " Interface address discovery supported through SIO_GET_INTERFACE_LIST.")
- ADD_DEFINITIONS(-DHAVE_WINSOCK2_H)
+ SET(IF_ADDRS_DEFS HAVE_WINSOCK2_H)
ELSE(HAVE_IFADDRS_H)
MESSAGE(STATUS " Interface address discovery not supported.")
ENDIF(HAVE_IFADDRS_H)
+SET_SOURCE_FILES_PROPERTIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp
+ PROPERTIES COMPILE_DEFINITIONS "${IF_ADDRS_DEFS}"
+)
+
########################################################################
# Append to the list of sources for lib uhd
########################################################################
@@ -75,6 +80,6 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/buffer_pool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/udp_simple.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_zero_copy_asio.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_zero_copy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vrt_packet_handler.hpp
)
diff --git a/host/lib/transport/udp_common.hpp b/host/lib/transport/udp_common.hpp
new file mode 100644
index 000000000..47775d9c4
--- /dev/null
+++ b/host/lib/transport/udp_common.hpp
@@ -0,0 +1,53 @@
+//
+// Copyright 2011 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/>.
+//
+
+#ifndef INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP
+#define INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP
+
+#include <uhd/config.hpp>
+#include <boost/asio.hpp>
+
+namespace uhd{ namespace transport{
+
+ typedef boost::shared_ptr<boost::asio::ip::udp::socket> socket_sptr;
+
+ /*!
+ * Wait for the socket to become ready for a receive operation.
+ * \param sock_fd the open socket file descriptor
+ * \param timeout the timeout duration in seconds
+ * \return true when the socket is ready for receive
+ */
+ UHD_INLINE bool wait_for_recv_ready(int sock_fd, double timeout){
+ //setup timeval for timeout
+ timeval tv;
+ //If the tv_usec > 1 second on some platforms, select will
+ //error EINVAL: An invalid timeout interval was specified.
+ tv.tv_sec = int(timeout);
+ tv.tv_usec = int(timeout*1000000)%1000000;
+
+ //setup rset for timeout
+ fd_set rset;
+ FD_ZERO(&rset);
+ FD_SET(sock_fd, &rset);
+
+ //call select with timeout on receive socket
+ return ::select(sock_fd+1, &rset, NULL, NULL, &tv) > 0;
+ }
+
+}} //namespace uhd::transport
+
+#endif /* INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP */
diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp
index 6799ac7b2..1ee036d52 100644
--- a/host/lib/transport/udp_simple.cpp
+++ b/host/lib/transport/udp_simple.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
@@ -15,159 +15,69 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include "udp_common.hpp"
#include <uhd/transport/udp_simple.hpp>
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
using namespace uhd::transport;
+namespace asio = boost::asio;
/***********************************************************************
- * Helper Functions
+ * UDP simple implementation: connected and broadcast
**********************************************************************/
-/*!
- * Wait for available data or timeout.
- * \param socket the asio socket
- * \param timeout the timeout in seconds
- * \return false for timeout, true for data
- */
-static bool wait_available(
- boost::asio::ip::udp::socket &socket, double timeout
-){
- #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)
-
- //setup timeval for timeout
- timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = long(timeout*1e6);
-
- //setup rset for timeout
- fd_set rset;
- FD_ZERO(&rset);
- FD_SET(socket.native(), &rset);
-
- return ::select(socket.native()+1, &rset, NULL, NULL, &tv) > 0;
-
- #else /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/
-
- //FIXME: why does select fail on macintosh?
- for (size_t i = 0; i < size_t(timeout*1e3); i++){
- if (socket.available()) return true;
- boost::this_thread::sleep(boost::posix_time::milliseconds(1));
- }
- return false;
-
- #endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/
-}
-
-/***********************************************************************
- * UDP connected implementation class
- **********************************************************************/
-class udp_connected_impl : public udp_simple{
+class udp_simple_impl : public udp_simple{
public:
- //structors
- udp_connected_impl(const std::string &addr, const std::string &port);
- ~udp_connected_impl(void);
-
- //send/recv
- size_t send(const boost::asio::const_buffer &);
- size_t recv(const boost::asio::mutable_buffer &, double);
-
-private:
- boost::asio::ip::udp::socket *_socket;
- boost::asio::io_service _io_service;
-};
+ udp_simple_impl(
+ const std::string &addr, const std::string &port, bool bcast, bool connect
+ ):_connected(connect){
+ //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl;
-udp_connected_impl::udp_connected_impl(const std::string &addr, const std::string &port){
- //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl;
+ //resolve the address
+ asio::ip::udp::resolver resolver(_io_service);
+ asio::ip::udp::resolver::query query(asio::ip::udp::v4(), addr, port);
+ _receiver_endpoint = *resolver.resolve(query);
- // resolve the address
- boost::asio::ip::udp::resolver resolver(_io_service);
- boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port);
- boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query);
+ //create and open the socket
+ _socket = socket_sptr(new asio::ip::udp::socket(_io_service));
+ _socket->open(asio::ip::udp::v4());
- // Create, open, and connect the socket
- _socket = new boost::asio::ip::udp::socket(_io_service);
- _socket->open(boost::asio::ip::udp::v4());
- _socket->connect(receiver_endpoint);
-}
+ //allow broadcasting
+ _socket->set_option(asio::socket_base::broadcast(bcast));
-udp_connected_impl::~udp_connected_impl(void){
- delete _socket;
-}
-
-size_t udp_connected_impl::send(const boost::asio::const_buffer &buff){
- return _socket->send(boost::asio::buffer(buff));
-}
+ //connect the socket
+ if (connect) _socket->connect(_receiver_endpoint);
-size_t udp_connected_impl::recv(const boost::asio::mutable_buffer &buff, double timeout){
- if (not wait_available(*_socket, timeout)) return 0;
- return _socket->receive(boost::asio::buffer(buff));
-}
+ }
-/***********************************************************************
- * UDP broadcast implementation class
- **********************************************************************/
-class udp_broadcast_impl : public udp_simple{
-public:
- //structors
- udp_broadcast_impl(const std::string &addr, const std::string &port);
- ~udp_broadcast_impl(void);
+ size_t send(const asio::const_buffer &buff){
+ if (_connected) return _socket->send(asio::buffer(buff));
+ return _socket->send_to(asio::buffer(buff), _receiver_endpoint);
+ }
- //send/recv
- size_t send(const boost::asio::const_buffer &);
- size_t recv(const boost::asio::mutable_buffer &, double);
+ size_t recv(const asio::mutable_buffer &buff, double timeout){
+ if (not wait_for_recv_ready(_socket->native(), timeout)) return 0;
+ return _socket->receive(asio::buffer(buff));
+ }
private:
- boost::asio::ip::udp::socket *_socket;
- boost::asio::ip::udp::endpoint _receiver_endpoint;
- boost::asio::io_service _io_service;
+ bool _connected;
+ asio::io_service _io_service;
+ socket_sptr _socket;
+ asio::ip::udp::endpoint _receiver_endpoint;
};
-udp_broadcast_impl::udp_broadcast_impl(const std::string &addr, const std::string &port){
- //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl;
-
- // resolve the address
- boost::asio::ip::udp::resolver resolver(_io_service);
- boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port);
- _receiver_endpoint = *resolver.resolve(query);
-
- // Create and open the socket
- _socket = new boost::asio::ip::udp::socket(_io_service);
- _socket->open(boost::asio::ip::udp::v4());
-
- // Allow broadcasting
- boost::asio::socket_base::broadcast option(true);
- _socket->set_option(option);
-
-}
-
-udp_broadcast_impl::~udp_broadcast_impl(void){
- delete _socket;
-}
-
-size_t udp_broadcast_impl::send(const boost::asio::const_buffer &buff){
- return _socket->send_to(boost::asio::buffer(buff), _receiver_endpoint);
-}
-
-size_t udp_broadcast_impl::recv(const boost::asio::mutable_buffer &buff, double timeout){
- if (not wait_available(*_socket, timeout)) return 0;
- boost::asio::ip::udp::endpoint sender_endpoint;
- return _socket->receive_from(boost::asio::buffer(buff), sender_endpoint);
-}
-
/***********************************************************************
* UDP public make functions
**********************************************************************/
udp_simple::sptr udp_simple::make_connected(
const std::string &addr, const std::string &port
){
- return sptr(new udp_connected_impl(addr, port));
+ return sptr(new udp_simple_impl(addr, port, false, true /* no bcast, connect */));
}
udp_simple::sptr udp_simple::make_broadcast(
const std::string &addr, const std::string &port
){
- return sptr(new udp_broadcast_impl(addr, port));
+ return sptr(new udp_simple_impl(addr, port, true, false /* bcast, no connect */));
}
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy.cpp
index 05352ffce..dda3bb547 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy.cpp
@@ -15,13 +15,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include "udp_common.hpp"
#include <uhd/transport/udp_zero_copy.hpp>
#include <uhd/transport/udp_simple.hpp> //mtu
#include <uhd/transport/bounded_buffer.hpp>
#include <uhd/transport/buffer_pool.hpp>
-#include <uhd/utils/assert.hpp>
#include <uhd/utils/warning.hpp>
-#include <boost/asio.hpp>
#include <boost/format.hpp>
#include <iostream>
#include <list>
@@ -140,7 +139,7 @@ public:
asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query);
//create, open, and connect the socket
- _socket = new asio::ip::udp::socket(_io_service);
+ _socket = socket_sptr(new asio::ip::udp::socket(_io_service));
_socket->open(asio::ip::udp::v4());
_socket->connect(receiver_endpoint);
_sock_fd = _socket->native();
@@ -162,10 +161,6 @@ public:
}
}
- ~udp_zero_copy_asio_impl(void){
- delete _socket;
- }
-
//get size for internal socket buffer
template <typename Opt> size_t get_buff_size(void) const{
Opt option;
@@ -183,30 +178,24 @@ public:
/*******************************************************************
* Receive implementation:
*
- * Use select to perform a blocking receive with timeout.
+ * Perform a non-blocking receive for performance,
+ * and then fall back to a blocking receive with timeout.
* Return the managed receive buffer with the new length.
* When the caller is finished with the managed buffer,
* the managed receive buffer is released back into the queue.
******************************************************************/
- UHD_INLINE bool is_recv_ready(double timeout){
- //setup timeval for timeout
- timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = long(timeout*1e6);
-
- //setup rset for timeout
- fd_set rset;
- FD_ZERO(&rset);
- FD_SET(_sock_fd, &rset);
-
- //call select with timeout on receive socket
- return ::select(_sock_fd+1, &rset, NULL, NULL, &tv) > 0;
- }
-
managed_recv_buffer::sptr get_recv_buff(double timeout){
udp_zero_copy_asio_mrb *mrb = NULL;
- if (is_recv_ready(timeout) and _pending_recv_buffs.pop_with_timed_wait(mrb, timeout)){
- return mrb->get_new(::recv(_sock_fd, mrb->cast<char *>(), _recv_frame_size, 0));
+ if (_pending_recv_buffs.pop_with_timed_wait(mrb, timeout)){
+
+ #ifdef MSG_DONTWAIT //try a non-blocking recv() if supported
+ ssize_t ret = ::recv(_sock_fd, mrb->cast<char *>(), _recv_frame_size, MSG_DONTWAIT);
+ if (ret > 0) return mrb->get_new(ret);
+ #endif
+
+ if (wait_for_recv_ready(_sock_fd, timeout)) return mrb->get_new(
+ ::recv(_sock_fd, mrb->cast<char *>(), _recv_frame_size, 0)
+ );
}
return managed_recv_buffer::sptr();
}
@@ -262,7 +251,7 @@ private:
//asio guts -> socket and service
asio::io_service _io_service;
- asio::ip::udp::socket *_socket;
+ socket_sptr _socket;
int _sock_fd;
};
diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt
index ad625111e..957dfd345 100644
--- a/host/lib/types/CMakeLists.txt
+++ b/host/lib/types/CMakeLists.txt
@@ -58,19 +58,24 @@ CHECK_CXX_SOURCE_COMPILES("
IF(HAVE_CLOCK_GETTIME)
MESSAGE(STATUS " High resolution timing supported through clock_gettime.")
- ADD_DEFINITIONS(-DTIME_SPEC_USE_CLOCK_GETTIME)
- SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lrt")
+ SET(TIME_SPEC_DEFS HAVE_CLOCK_GETTIME)
+ LIBUHD_APPEND_LIBS("-lrt")
ELSEIF(HAVE_MACH_ABSOLUTE_TIME)
MESSAGE(STATUS " High resolution timing supported through mach_absolute_time.")
- ADD_DEFINITIONS(-DTIME_SPEC_USE_MACH_ABSOLUTE_TIME)
+ SET(TIME_SPEC_DEFS HAVE_MACH_ABSOLUTE_TIME)
ELSEIF(HAVE_QUERY_PERFORMANCE_COUNTER)
MESSAGE(STATUS " High resolution timing supported through QueryPerformanceCounter.")
- ADD_DEFINITIONS(-DTIME_SPEC_USE_QUERY_PERFORMANCE_COUNTER)
+ SET(TIME_SPEC_DEFS HAVE_QUERY_PERFORMANCE_COUNTER)
ELSE()
MESSAGE(STATUS " High resolution timing supported though microsec_clock.")
- ADD_DEFINITIONS(-DTIME_SPEC_USE_MICROSEC_CLOCK)
+ SET(TIME_SPEC_DEFS HAVE_MICROSEC_CLOCK)
ENDIF()
+SET_SOURCE_FILES_PROPERTIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/time_spec.cpp
+ PROPERTIES COMPILE_DEFINITIONS "${TIME_SPEC_DEFS}"
+)
+
########################################################################
# This file included, use CMake directory variables
########################################################################
diff --git a/host/lib/types/time_spec.cpp b/host/lib/types/time_spec.cpp
index 4a41f0fb9..a785332c2 100644
--- a/host/lib/types/time_spec.cpp
+++ b/host/lib/types/time_spec.cpp
@@ -36,26 +36,26 @@ static UHD_INLINE time_spec_t time_spec_t_from_counts(intmax_t counts, intmax_t
return time_spec_t(time_t(divres.quot), double(divres.rem)/freq);
}
-#ifdef TIME_SPEC_USE_CLOCK_GETTIME
+#ifdef HAVE_CLOCK_GETTIME
#include <time.h>
time_spec_t time_spec_t::get_system_time(void){
timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);
return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9);
}
-#endif /* TIME_SPEC_USE_CLOCK_GETTIME */
+#endif /* HAVE_CLOCK_GETTIME */
-#ifdef TIME_SPEC_USE_MACH_ABSOLUTE_TIME
+#ifdef HAVE_MACH_ABSOLUTE_TIME
#include <mach/mach_time.h>
time_spec_t time_spec_t::get_system_time(void){
mach_timebase_info_data_t info; mach_timebase_info(&info);
intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom;
return time_spec_t_from_counts(nanosecs, intmax_t(1e9));
}
-#endif /* TIME_SPEC_USE_MACH_ABSOLUTE_TIME */
+#endif /* HAVE_MACH_ABSOLUTE_TIME */
-#ifdef TIME_SPEC_USE_QUERY_PERFORMANCE_COUNTER
+#ifdef HAVE_QUERY_PERFORMANCE_COUNTER
#include <Windows.h>
time_spec_t time_spec_t::get_system_time(void){
LARGE_INTEGER counts, freq;
@@ -63,10 +63,10 @@ time_spec_t time_spec_t::get_system_time(void){
QueryPerformanceFrequency(&freq);
return time_spec_t_from_counts(counts.QuadPart, freq.QuadPart);
}
-#endif /* TIME_SPEC_USE_QUERY_PERFORMANCE_COUNTER */
+#endif /* HAVE_QUERY_PERFORMANCE_COUNTER */
-#ifdef TIME_SPEC_USE_MICROSEC_CLOCK
+#ifdef HAVE_MICROSEC_CLOCK
#include <boost/date_time/posix_time/posix_time.hpp>
namespace pt = boost::posix_time;
time_spec_t time_spec_t::get_system_time(void){
@@ -78,7 +78,7 @@ time_spec_t time_spec_t::get_system_time(void){
double(pt::time_duration::ticks_per_second())
);
}
-#endif /* TIME_SPEC_USE_MICROSEC_CLOCK */
+#endif /* HAVE_MICROSEC_CLOCK */
/***********************************************************************
* Time spec constructors
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
index 5fa5b4d6d..743528189 100644
--- a/host/lib/utils/CMakeLists.txt
+++ b/host/lib/utils/CMakeLists.txt
@@ -48,14 +48,19 @@ CHECK_CXX_SOURCE_COMPILES("
IF(HAVE_PTHREAD_SETSCHEDPARAM)
MESSAGE(STATUS " Priority scheduling supported through pthread_setschedparam.")
- ADD_DEFINITIONS(-DHAVE_PTHREAD_SETSCHEDPARAM)
+ SET(THREAD_PRIO_DEFS HAVE_PTHREAD_SETSCHEDPARAM)
ELSEIF(HAVE_WIN_SETTHREADPRIORITY)
MESSAGE(STATUS " Priority scheduling supported through windows SetThreadPriority.")
- ADD_DEFINITIONS(-DHAVE_WIN_SETTHREADPRIORITY)
+ SET(THREAD_PRIO_DEFS HAVE_WIN_SETTHREADPRIORITY)
ELSE(HAVE_PTHREAD_SETSCHEDPARAM)
MESSAGE(STATUS " Priority scheduling not supported.")
ENDIF(HAVE_PTHREAD_SETSCHEDPARAM)
+SET_SOURCE_FILES_PROPERTIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp
+ PROPERTIES COMPILE_DEFINITIONS "${THREAD_PRIO_DEFS}"
+)
+
########################################################################
# Setup defines for module loading
########################################################################
@@ -68,15 +73,20 @@ CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H)
IF(HAVE_DLFCN_H)
MESSAGE(STATUS " Module loading supported through dlopen.")
- ADD_DEFINITIONS(-DHAVE_DLFCN_H)
+ SET(LOAD_MODULES_DEFS HAVE_DLFCN_H)
LIBUHD_APPEND_LIBS(${CMAKE_DL_LIBS})
ELSEIF(HAVE_WINDOWS_H)
MESSAGE(STATUS " Module loading supported through LoadLibrary.")
- ADD_DEFINITIONS(-DHAVE_WINDOWS_H)
+ SET(LOAD_MODULES_DEFS HAVE_WINDOWS_H)
ELSE(HAVE_DLFCN_H)
MESSAGE(STATUS " Module loading not supported.")
ENDIF(HAVE_DLFCN_H)
+SET_SOURCE_FILES_PROPERTIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp
+ PROPERTIES COMPILE_DEFINITIONS "${LOAD_MODULES_DEFS}"
+)
+
########################################################################
# Append sources
########################################################################
diff --git a/host/utils/usrp_n2xx_net_burner.py b/host/utils/usrp_n2xx_net_burner.py
index db94d50a4..6fdc9df20 100755
--- a/host/utils/usrp_n2xx_net_burner.py
+++ b/host/utils/usrp_n2xx_net_burner.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 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
@@ -27,7 +27,7 @@ import re
import struct
import socket
import sys
-import os.path
+import time
########################################################################
# constants
@@ -76,77 +76,28 @@ class update_id_t:
_seq = -1
def seq():
- global _seq
- _seq = _seq+1
- return _seq
+ global _seq
+ _seq = _seq+1
+ return _seq
########################################################################
# helper functions
########################################################################
def unpack_flash_args_fmt(s):
- return struct.unpack(FLASH_ARGS_FMT, s) #(proto_ver, pktid, seq, flash_addr, length, data)
+ return struct.unpack(FLASH_ARGS_FMT, s) #(proto_ver, pktid, seq, flash_addr, length, data)
def unpack_flash_info_fmt(s):
- return struct.unpack(FLASH_INFO_FMT, s) #(proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes)
+ return struct.unpack(FLASH_INFO_FMT, s) #(proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes)
def unpack_flash_ip_fmt(s):
- return struct.unpack(FLASH_IP_FMT, s) #(proto_ver, pktid, seq, ip_addr)
+ return struct.unpack(FLASH_IP_FMT, s) #(proto_ver, pktid, seq, ip_addr)
def pack_flash_args_fmt(proto_ver, pktid, seq, flash_addr, length, data):
- return struct.pack(FLASH_ARGS_FMT, proto_ver, pktid, seq, flash_addr, length, data)
+ return struct.pack(FLASH_ARGS_FMT, proto_ver, pktid, seq, flash_addr, length, data)
def pack_flash_info_fmt(proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes):
- return struct.pack(FLASH_INFO_FMT, proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes)
+ return struct.pack(FLASH_INFO_FMT, proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes)
-def send_and_recv(pkt, ip):
- update_socket = create_socket()
-
- try:
- update_socket.sendto(pkt, (ip, UDP_FW_UPDATE_PORT))
- except Exception, e:
- print e
- sys.exit(1)
-
- try:
- (recv_pkt, recv_addr) = update_socket.recvfrom(UDP_MAX_XFER_BYTES)
- except Exception, e:
- print e
- sys.exit(1)
-
- if recv_addr != (options.ip, UDP_FW_UPDATE_PORT):
- raise Exception, "Packet received from invalid IP %s, expected %s" % (recv_addr, options.ip)
-
- return recv_pkt
-
-def create_socket():
- socket.setdefaulttimeout(UDP_TIMEOUT)
- update_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- return update_socket
-
-#just here to validate comms
-def init_update(ip):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_OHAI_LOL, seq(), 0, 0, "")
- in_pkt = send_and_recv(out_pkt, ip)
- (proto_ver, pktid, rxseq, ip_addr) = unpack_flash_ip_fmt(in_pkt)
- if pktid == update_id_t.USRP2_FW_UPDATE_ID_OHAI_OMG:
- print "USRP2P found."
- else:
- raise Exception, "Invalid reply received from device."
-
-# print "Incoming:\n\tVer: %i\n\tID: %c\n\tSeq: %i\n\tIP: %i\n" % (proto_ver, chr(pktid), rxseq, ip_addr)
-
-def get_flash_info(ip):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL, seq(), 0, 0, "")
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, sector_size_bytes, memory_size_bytes) = unpack_flash_info_fmt(in_pkt)
-
- if pktid != update_id_t.USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
-
-
- return (memory_size_bytes, sector_size_bytes)
-
def is_valid_fpga_image(fpga_image):
for i in range(0,63):
if ord(fpga_image[i]) == 0xFF:
@@ -155,7 +106,7 @@ def is_valid_fpga_image(fpga_image):
return 1
return 0
-
+
def is_valid_fw_image(fw_image):
for i in range(0,4):
if ord(fw_image[i]) != 0x0B:
@@ -163,158 +114,205 @@ def is_valid_fw_image(fw_image):
return 1
-def burn_fw(ip, fw, fpga, reset, safe):
- init_update(ip)
- (flash_size, sector_size) = get_flash_info(ip)
-
- print "Flash size: %i\nSector size: %i" % (flash_size, sector_size)
-
- if fpga:
- if safe:
- image_location = SAFE_FPGA_IMAGE_LOCATION_ADDR
- else:
- image_location = PROD_FPGA_IMAGE_LOCATION_ADDR
-
- fpga_file = open(fpga, 'rb')
- fpga_image = fpga_file.read()
-
- if len(fpga_image) > FPGA_IMAGE_SIZE_BYTES:
- print "Error: FPGA image file too large."
- return 0
-
- if not is_valid_fpga_image(fpga_image):
- print "Error: Invalid FPGA image file."
- return 0
-
- erase_image(ip, image_location, FPGA_IMAGE_SIZE_BYTES)
- write_image(ip, fpga_image, image_location)
- verify_image(ip, fpga_image, image_location)
-
- if fw:
- if safe:
- image_location = SAFE_FW_IMAGE_LOCATION_ADDR
- else:
- image_location = PROD_FW_IMAGE_LOCATION_ADDR
-
- fw_file = open(fw, 'rb')
- fw_image = fw_file.read()
-
- if len(fw_image) > FW_IMAGE_SIZE_BYTES:
- print "Error: Firmware image file too large."
- return 0
-
- if not is_valid_fw_image(fw_image):
- print "Error: Invalid firmware image file."
- return 0
-
- erase_image(ip, image_location, FW_IMAGE_SIZE_BYTES)
- write_image(ip, fw_image, image_location)
- verify_image(ip, fw_image, image_location)
-
- if reset:
- reset_usrp(ip)
-
-def write_image(ip, image, addr):
- print "Writing image"
-#we split the image into smaller (256B) bits and send them down the wire
- while image:
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL, seq(), addr, FLASH_DATA_PACKET_SIZE, image[:FLASH_DATA_PACKET_SIZE])
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
-
- if pktid != update_id_t.USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
-
- image = image[FLASH_DATA_PACKET_SIZE:]
- addr += FLASH_DATA_PACKET_SIZE
-
-def verify_image(ip, image, addr):
- print "Verifying data"
- readsize = len(image)
- readdata = str()
- while readsize > 0:
- if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize
- else: thisreadsize = FLASH_DATA_PACKET_SIZE
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "")
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
-
- if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
-
- readdata += data[:thisreadsize]
- readsize -= FLASH_DATA_PACKET_SIZE
- addr += FLASH_DATA_PACKET_SIZE
-
- print "Read back %i bytes" % len(readdata)
-# print readdata
-
-# for i in range(256, 512):
-# print "out: %i in: %i" % (ord(image[i]), ord(readdata[i]))
-
- if readdata != image:
- print "Verify failed. Image did not write correctly."
- else:
- print "Success."
-
-def read_flash(ip, image, size, addr):
- print "Reading image"
- readsize = size
- readdata = str()
- while readsize > 0:
- if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize
- else: thisreadsize = FLASH_DATA_PACKET_SIZE
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "")
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
-
- if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
-
- readdata += data[:thisreadsize]
- readsize -= FLASH_DATA_PACKET_SIZE
- addr += FLASH_DATA_PACKET_SIZE
-
- print "Read back %i bytes" % len(readdata)
-
- #write to disk
- f = open(image, 'w')
- f.write(readdata)
- f.close()
-
-def reset_usrp(ip):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL, seq(), 0, 0, "")
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
- if pktid == update_id_t.USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG:
- raise Exception, "Device failed to reset."
-
-def erase_image(ip, addr, length):
- #get flash info first
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL, seq(), addr, length, "")
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
-
- if pktid != update_id_t.USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
-
- print "Erasing %i bytes at %i" % (length, addr)
-
- #now wait for it to finish
- while(1):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL, seq(), 0, 0, "")
- in_pkt = send_and_recv(out_pkt, ip)
-
- (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
-
- if pktid == update_id_t.USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG: break
- elif pktid != update_id_t.USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+########################################################################
+# Burner class, holds a socket and send/recv routines
+########################################################################
+class burner_socket(object):
+ def __init__(self, ip):
+ self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self._sock.settimeout(UDP_TIMEOUT)
+ self._sock.connect((ip, UDP_FW_UPDATE_PORT))
+
+ def send_and_recv(self, pkt):
+ try: self._sock.send(pkt)
+ except Exception, e:
+ print e
+ sys.exit(1)
+
+ try: recv_pkt = self._sock.recv(UDP_MAX_XFER_BYTES)
+ except Exception, e:
+ print e
+ sys.exit(1)
+
+ return recv_pkt
+
+ #just here to validate comms
+ def init_update(self):
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_OHAI_LOL, seq(), 0, 0, "")
+ in_pkt = self.send_and_recv(out_pkt)
+ (proto_ver, pktid, rxseq, ip_addr) = unpack_flash_ip_fmt(in_pkt)
+ if pktid == update_id_t.USRP2_FW_UPDATE_ID_OHAI_OMG:
+ print "USRP2P found."
+ else:
+ raise Exception, "Invalid reply received from device."
+
+ # print "Incoming:\n\tVer: %i\n\tID: %c\n\tSeq: %i\n\tIP: %i\n" % (proto_ver, chr(pktid), rxseq, ip_addr)
+
+ def get_flash_info(self):
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL, seq(), 0, 0, "")
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, sector_size_bytes, memory_size_bytes) = unpack_flash_info_fmt(in_pkt)
+
+ if pktid != update_id_t.USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG:
+ raise Exception, "Invalid reply %c from device." % (chr(pktid))
+
+ return (memory_size_bytes, sector_size_bytes)
+
+ def burn_fw(self, fw, fpga, reset, safe):
+ (flash_size, sector_size) = self.get_flash_info()
+
+ print "Flash size: %i\nSector size: %i\n\n" % (flash_size, sector_size)
+
+ if fpga:
+ if safe: image_location = SAFE_FPGA_IMAGE_LOCATION_ADDR
+ else: image_location = PROD_FPGA_IMAGE_LOCATION_ADDR
+
+ fpga_file = open(fpga, 'rb')
+ fpga_image = fpga_file.read()
+
+ if len(fpga_image) > FPGA_IMAGE_SIZE_BYTES:
+ print "Error: FPGA image file too large."
+ return 0
+
+ if not is_valid_fpga_image(fpga_image):
+ print "Error: Invalid FPGA image file."
+ return 0
+
+ print "Begin FPGA write: this should take about 1 minute..."
+ start_time = time.time()
+ self.erase_image(image_location, FPGA_IMAGE_SIZE_BYTES)
+ self.write_image(fpga_image, image_location)
+ self.verify_image(fpga_image, image_location)
+ print "Time elapsed: %f seconds"%(time.time() - start_time)
+ print "\n\n"
+
+ if fw:
+ if safe: image_location = SAFE_FW_IMAGE_LOCATION_ADDR
+ else: image_location = PROD_FW_IMAGE_LOCATION_ADDR
+
+ fw_file = open(fw, 'rb')
+ fw_image = fw_file.read()
+
+ if len(fw_image) > FW_IMAGE_SIZE_BYTES:
+ print "Error: Firmware image file too large."
+ return 0
+
+ if not is_valid_fw_image(fw_image):
+ print "Error: Invalid firmware image file."
+ return 0
+
+ print "Begin firmware write: this should take about 1 second..."
+ start_time = time.time()
+ self.erase_image(image_location, FW_IMAGE_SIZE_BYTES)
+ self.write_image(fw_image, image_location)
+ self.verify_image(fw_image, image_location)
+ print "Time elapsed: %f seconds"%(time.time() - start_time)
+ print "\n\n"
+
+ if reset: self.reset_usrp()
+
+ def write_image(self, image, addr):
+ print "Writing image"
+ #we split the image into smaller (256B) bits and send them down the wire
+ while image:
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL, seq(), addr, FLASH_DATA_PACKET_SIZE, image[:FLASH_DATA_PACKET_SIZE])
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
+
+ if pktid != update_id_t.USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG:
+ raise Exception, "Invalid reply %c from device." % (chr(pktid))
+
+ image = image[FLASH_DATA_PACKET_SIZE:]
+ addr += FLASH_DATA_PACKET_SIZE
+
+ def verify_image(self, image, addr):
+ print "Verifying data"
+ readsize = len(image)
+ readdata = str()
+ while readsize > 0:
+ if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize
+ else: thisreadsize = FLASH_DATA_PACKET_SIZE
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "")
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
+
+ if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG:
+ raise Exception, "Invalid reply %c from device." % (chr(pktid))
+
+ readdata += data[:thisreadsize]
+ readsize -= FLASH_DATA_PACKET_SIZE
+ addr += FLASH_DATA_PACKET_SIZE
+
+ print "Read back %i bytes" % len(readdata)
+ # print readdata
+
+ # for i in range(256, 512):
+ # print "out: %i in: %i" % (ord(image[i]), ord(readdata[i]))
+
+ if readdata != image:
+ print "Verify failed. Image did not write correctly."
+ else:
+ print "Success."
+
+ def read_image(self, image, size, addr):
+ print "Reading image"
+ readsize = size
+ readdata = str()
+ while readsize > 0:
+ if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize
+ else: thisreadsize = FLASH_DATA_PACKET_SIZE
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "")
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
+
+ if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG:
+ raise Exception, "Invalid reply %c from device." % (chr(pktid))
+
+ readdata += data[:thisreadsize]
+ readsize -= FLASH_DATA_PACKET_SIZE
+ addr += FLASH_DATA_PACKET_SIZE
+
+ print "Read back %i bytes" % len(readdata)
+
+ #write to disk
+ f = open(image, 'w')
+ f.write(readdata)
+ f.close()
+
+ def reset_usrp(self):
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL, seq(), 0, 0, "")
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
+ if pktid == update_id_t.USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG:
+ raise Exception, "Device failed to reset."
+
+ def erase_image(self, addr, length):
+ #get flash info first
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL, seq(), addr, length, "")
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
+
+ if pktid != update_id_t.USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG:
+ raise Exception, "Invalid reply %c from device." % (chr(pktid))
+
+ print "Erasing %i bytes at %i" % (length, addr)
+
+ #now wait for it to finish
+ while(True):
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL, seq(), 0, 0, "")
+ in_pkt = self.send_and_recv(out_pkt)
+
+ (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
+
+ if pktid == update_id_t.USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG: break
+ elif pktid != update_id_t.USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG:
+ raise Exception, "Invalid reply %c from device." % (chr(pktid))
########################################################################
@@ -340,33 +338,32 @@ if __name__=='__main__':
if not options.ip: raise Exception, 'no ip address specified'
if not options.fpga and not options.fw and not options.reset: raise Exception, 'Must specify either a firmware image or FPGA image, and/or reset.'
-
+
if options.overwrite_safe and not options.read:
print("Are you REALLY, REALLY sure you want to overwrite the safe image? This is ALMOST ALWAYS a terrible idea.")
print("If your image is faulty, your USRP2+ will become a brick until reprogrammed via JTAG.")
response = raw_input("""Type "yes" to continue, or anything else to quit: """)
- if response != "yes":
- sys.exit(0)
-
- if options.read is True:
+ if response != "yes": sys.exit(0)
+
+ burner = burner_socket(ip=options.ip)
+
+ if options.read:
if options.fw:
file = options.fw
if os.path.isfile(file):
response = raw_input("File already exists -- overwrite? (y/n) ")
- if response != "y":
- sys.exit(0)
+ if response != "y": sys.exit(0)
size = FW_IMAGE_SIZE_BYTES
addr = SAFE_FW_IMAGE_LOCATION_ADDR if options.overwrite_safe else PROD_FW_IMAGE_LOCATION_ADDR
- read_flash(options.ip, file, size, addr)
- if options.fpga:
+ burner.read_image(file, size, addr)
+
+ if options.fpga:
file = options.fpga
if os.path.isfile(file):
response = raw_input("File already exists -- overwrite? (y/n) ")
- if response != "y":
- sys.exit(0)
+ if response != "y": sys.exit(0)
size = FPGA_IMAGE_SIZE_BYTES
addr = SAFE_FPGA_IMAGE_LOCATION_ADDR if options.overwrite_safe else PROD_FPGA_IMAGE_LOCATION_ADDR
- read_flash(options.ip, file, size, addr)
-
- else:
- burn_fw(ip=options.ip, fw=options.fw, fpga=options.fpga, reset=options.reset, safe=options.overwrite_safe)
+ burner.read_image(file, size, addr)
+
+ else: burner.burn_fw(fw=options.fw, fpga=options.fpga, reset=options.reset, safe=options.overwrite_safe)