diff options
24 files changed, 563 insertions, 2207 deletions
| diff --git a/firmware/zpu/lib/clock_bits.h b/firmware/zpu/lib/clock_bits.h deleted file mode 100644 index d2052e941..000000000 --- a/firmware/zpu/lib/clock_bits.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -/* - * Copyright 2008 Free Software Foundation, Inc. - *  - * This file is part of GNU Radio - *  - * GNU Radio 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, or (at your option) - * any later version. - *  - * GNU Radio 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, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef INCLUDED_USRP2_CLOCK_BITS_H -#define INCLUDED_USRP2_CLOCK_BITS_H - -#define	_MC_WE_LOCK			0x0001 -#define	_MC_MIMO_CLK_INPUT		0x0002		// else SMA input - -/* - * Derived masks (use these): - * - * We get our input from 1 of three places: - *  Our free running oscilator, our SMA connector, or from the MIMO connector - */ -#define	MC_WE_DONT_LOCK			0x0000 -#define	MC_WE_LOCK_TO_SMA		(_MC_WE_LOCK | 0) -#define	MC_WE_LOCK_TO_MIMO		(_MC_WE_LOCK | _MC_MIMO_CLK_INPUT) - -/* - * Independent of the source of the clock, we may or may not drive our - * clock onto the mimo connector.  Note that there are dedicated clock - * signals in each direction, so disaster doesn't occurs if we're - * unnecessarily providing clock. - */ -#define	MC_PROVIDE_CLK_TO_MIMO		0x0004 - -#define MC_REF_CLK_MASK          0x0f - -#define MC_PPS_SOURCE_SMA        (0x00 << 4) -#define MC_PPS_SOURCE_MIMO       (0x01 << 4) - -#define MC_PPS_POLARITY_NEG      (0x00 << 5) -#define MC_PPS_POLARITY_POS      (0x01 << 5) - -#endif /* INCLUDED_USRP2_CLOCK_BITS_H */ diff --git a/firmware/zpu/lib/clocks.c b/firmware/zpu/lib/clocks.c index 2b352a385..c1e8ce827 100644 --- a/firmware/zpu/lib/clocks.c +++ b/firmware/zpu/lib/clocks.c @@ -1,4 +1,6 @@ -/* -*- c++ -*- */ +// +// Copyright 2010-2011 Ettus Research LLC +//  /*   * Copyright 2008 Free Software Foundation, Inc.   * @@ -16,119 +18,39 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif  #include <clocks.h> - +#include <stdbool.h>  #include "memory_map.h"  #include "ad9510.h"  #include "spi.h" -#include "u2_init.h" -//USRP2PLUS clocks: -//Clock 0: testclk -//Clock 1: FPGA clk -//Clock 2: ADC clk -//Clock 3: DAC clk -//Clock 4: SER clk -//Clock 5: TX dboard clk -//Clock 6: EXP clk -//Clock 7: RX dboard clk +/*! + * \brief Lock Detect -- Return True if our PLL is locked + */ +bool clocks_lock_detect(); -//TODO: should have enough brains to init the FPGA clock for USRP2+. all others are suspect. -//note that without EEPROM support u2_hw_rev_major is going to be incorrect. +/*! + * \brief Enable or disable fpga clock.  Disabling would wedge and require a power cycle. + */ +void clocks_enable_fpga_clk(bool enable, int divisor);  void   clocks_init(void)  {    // Set up basic clocking functions in AD9510 -  ad9510_write_reg(0x45, 0x01); // CLK2 drives distribution +  ad9510_write_reg(0x45, 0x01);    //enable the 100MHz clock output to the FPGA for 50MHz CPU clock    clocks_enable_fpga_clk(true, 1);    spi_wait(); -  // Set up PLL for 10 MHz reference -  // Reg 4, A counter, Don't Care -//  ad9510_write_reg(0x05, 0x00);  // Reg 5, B counter MSBs, 0 -//  ad9510_write_reg(0x06, 0x05);  // Reg 6, B counter LSBs, 5 -  // Reg 7, Loss of reference detect, doesn't work yet, 0 -//  ad9510_write_reg(0x5A, 0x01); // Update Regs - -  // Primary clock configuration -//  clocks_mimo_config(MC_WE_DONT_LOCK); - -    //wait for the clock to stabilize    while(!clocks_lock_detect());    //issue a reset to the DCM so it locks up to the new freq    output_regs->clk_ctrl |= CLK_RESET; - -  // Set up other clocks -  //clocks_enable_test_clk(false, 0); -  //clocks_enable_tx_dboard(false, 0); -  //clocks_enable_rx_dboard(false, 0); -//  clocks_enable_eth_phyclk(false, 0); //PHY clk is separate now (u2r4, u2p) - -  // Enable clock to ADCs and DACs -  //clocks_enable_dac_clk(true, 1); -  //clocks_enable_adc_clk(true, 1); -} - -/* -void -clocks_mimo_config(int flags) -{ -  if (flags & _MC_WE_LOCK){ -    // Reg 8, Charge pump on, dig lock det, positive PFD, 47 -    ad9510_write_reg(0x08, 0x47); -  } -  else { -    // Reg 8, Charge pump off, dig lock det, positive PFD -    ad9510_write_reg(0x08, 0x00); -  } -   -  // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA -  ad9510_write_reg(0x09, 0x00); -  // Reg A, Prescaler of 2, everything normal 04 -  ad9510_write_reg(0x0A, 0x04); -  // Reg B, R Div MSBs, 0 -  ad9510_write_reg(0x0B, 0x00); -  // Reg C, R Div LSBs, 1 -  ad9510_write_reg(0x0C, 0x01); -  // Reg D, Antibacklash, Digital lock det, 0 - -  ad9510_write_reg(0x5A, 0x01); // Update Regs - -  spi_wait(); -   -  // Allow for clock switchover -  // The below masks include 0x10, which issues a reset to the DCM.   -  if (flags & _MC_WE_LOCK){		// WE LOCK -    if (flags & _MC_MIMO_CLK_INPUT) { -      // Turn on ref output and choose the MIMO connector -      output_regs->clk_ctrl = 0x15;   -    } -    else { -      // turn on ref output and choose the SMA -      output_regs->clk_ctrl = 0x1C;  -    } -  } -  else {				// WE DONT LOCK -    // Disable both ext clk inputs -    output_regs->clk_ctrl = 0x10; -  } - -  // Do we drive a clock onto the MIMO connector? -//  if (flags & MC_PROVIDE_CLK_TO_MIMO) -//    clocks_enable_clkexp_out(true,10); -//  else -//    clocks_enable_clkexp_out(false,0);   } -*/  bool   clocks_lock_detect() @@ -188,79 +110,9 @@ clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mod    ad9510_write_reg(0x5A, 0x01);  // Update Regs  } -// Clock 0 -/*void -clocks_enable_test_clk(bool enable, int divisor) -{ -  clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); -}*/ -  // Clock 1  void  clocks_enable_fpga_clk(bool enable, int divisor)  {    clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL);  } -/* -// Clock 2 on Rev 3, Clock 5 on Rev 4, Clock 6 on USRP2+ -void -clocks_enable_clkexp_out(bool enable, int divisor) -{ -  if(u2_hw_rev_major == 3) -    clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); -  else if(u2_hw_rev_major == 4) { -    ad9510_write_reg(0x34,0x00);  // Turn on fine delay -    ad9510_write_reg(0x35,0x00);  // Set Full Scale to nearly 10ns -    ad9510_write_reg(0x36,0x1c);  // Set fine delay.  0x20 is midscale -    clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); -  } -	else if(u2_hw_rev_major == 10) { -		ad9510_write_reg(0x34, 0x00); -		ad9510_write_reg(0x35, 0x00); -		ad9510_write_reg(0x36, 0x1C); -		clocks_enable_XXX_clk(enable, divisor, 0x42, 0x52, CLOCK_MODE_LVDS); -	} -  else -    putstr("ERR (clocks_enable_clkexp_out): Invalid hw rev, don't know what to do!\n"); -} -*/ -/* -// Clock 5 on Rev 3, none (was 2) on Rev 4, none on USRP2+ -void -clocks_enable_eth_phyclk(bool enable, int divisor) -{ -  if(u2_hw_rev_major == 3) -    clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); -  else if(u2_hw_rev_major == 4) -    clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); -  else -    putstr("(clocks_enable_eth_phyclk): no eth PHY clock or invalid hw rev\n"); //not really an error -} -*/ -// Clock 3 -/*void -clocks_enable_dac_clk(bool enable, int divisor) -{ -  clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); -}*/ - -// Clock 4 -/*void -clocks_enable_adc_clk(bool enable, int divisor) -{ -  clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); -}*/ - -// Clock 6 -/*void -clocks_enable_tx_dboard(bool enable, int divisor) -{ -  clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); -}*/ - -// Clock 7 -/*void -clocks_enable_rx_dboard(bool enable, int divisor) -{ -  clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); -}*/ diff --git a/firmware/zpu/lib/clocks.h b/firmware/zpu/lib/clocks.h index 28d1d542f..7bc7a3cda 100644 --- a/firmware/zpu/lib/clocks.h +++ b/firmware/zpu/lib/clocks.h @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC  //  /*   * Copyright 2008 Free Software Foundation, Inc. @@ -21,75 +21,10 @@  #ifndef INCLUDED_CLOCKS_H  #define INCLUDED_CLOCKS_H -/* - * Routines to configure our multitude of clocks - */ - -#include <stdbool.h> -#include "clock_bits.h" - -  /*! - * One time call to initialize all clocks to a reasonable state.  We - * come out of here using our free running 100MHz oscilator and not - * providing a clock to the MIMO connector (CMC_WE_DONT_LOCK) + * One time call to initialize the master clock to a reasonable state. + * We come out of here using our free running 100MHz oscillator.   */  void clocks_init(void); - -/*! - * \brief MIMO clock configuration. - * - * Configure our master clock source, and whether or not we drive a - * clock onto the mimo connector.  See MC_flags in usrp2_mimo_config.h. - */ -//void clocks_mimo_config(int flags); - -/*! - * \brief Lock Detect -- Return True if our PLL is locked - */ -bool clocks_lock_detect(); - -/*! - * \brief Enable or disable test clock (extra clock signal) - */ -//void clocks_enable_test_clk(bool enable, int divisor); - -/*! - * \brief Enable or disable fpga clock.  Disabling would wedge and require a power cycle. - */ -void clocks_enable_fpga_clk(bool enable, int divisor); - -/*! - * \brief Enable or disable clock output sent to MIMO connector - */ -//void clocks_enable_clkexp_out(bool enable, int divisor); - -/*! - * \brief Enable or disable ethernet phyclk, should always be disabled - */ -//void clocks_enable_eth_phyclk(bool enable, int divisor); - -/*! - * \brief Enable or disable clock to DAC - */ -//void clocks_enable_dac_clk(bool enable, int divisor); - -/*! - * \brief Enable or disable clock to ADC - */ -//void clocks_enable_adc_clk(bool enable, int divisor); - -/*! - * \brief Enable or disable clock to Rx daughterboard - */ -//void clocks_enable_rx_dboard(bool enable, int divisor); - - -/*! - * \brief Enable or disable clock to Tx daughterboard - */ -//void clocks_enable_tx_dboard(bool enable, int divisor); - -  #endif /* INCLUDED_CLOCKS_H */ diff --git a/host/apps/omap_debug/Makefile b/host/apps/omap_debug/Makefile index 46d4714a8..f8b9f2bd9 100644 --- a/host/apps/omap_debug/Makefile +++ b/host/apps/omap_debug/Makefile @@ -1,27 +1,12 @@  CFLAGS=-Wall -I../../lib/usrp/usrp_e/ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -O3  CXXFLAGS=-Wall -I../../lib/usrp/usrp_e/ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -O3 -all : usrp-e-spi usrp-e-i2c usrp-e-loopback usrp-e-mm-loopback usrp-e-uart usrp-e-led usrp-e-ctl usrp-e-button usrp-e-uart-rx fpga-downloader usrp-e-gpio usrp-e-debug-pins usrp-e-random-loopback usrp-e-timed usrp-e-lb-test usrp-e-crc-rw clkgen-config +all : usrp-e-spi usrp-e-i2c usrp-e-uart usrp-e-led usrp-e-ctl usrp-e-button usrp-e-uart-rx usrp-e-gpio usrp-e-debug-pins  usrp-e-spi : usrp-e-spi.c  usrp-e-i2c : usrp-e-i2c.c -usrp-e-loopback : usrp-e-loopback.c -	gcc -o $@ $< -lpthread ${CFLAGS} - -usrp-e-mm-loopback : usrp-e-mm-loopback.c -	gcc -o $@ $< -lpthread ${CFLAGS} - -usrp-e-timed : usrp-e-timed.c -	gcc -o $@ $< -lpthread ${CFLAGS} - -usrp-e-random-loopback : usrp-e-random-loopback.c -	gcc -o $@ $< -lpthread ${CFLAGS} - -usrp-e-crc-rw : usrp-e-crc-rw.c -	gcc -o $@ $< -lpthread ${CFLAGS} -  usrp-e-uart : usrp-e-uart.c  usrp-e-uart-rx : usrp-e-uart-rx.c @@ -32,30 +17,17 @@ usrp-e-ctl : usrp-e-ctl.c  usrp-e-button : usrp-e-button.c -fpga-downloader : fpga-downloader.cc - -clkgen-config : clkgen-config.cc -  usrp-e-gpio : usrp-e-gpio.c -usrp-e-lb-test : usrp-e-lb-test.c -  usrp-e-debug-pins : usrp-e-debug-pins.c  clean :  	rm -f usrp-e-spi  	rm -f usrp-e-i2c -	rm -f usrp-e-loopback -	rm -f usrp-e-mm-loopback -	rm -f usrp-e-timed -	rm -f usrp-e-rw-random  	rm -f usrp-e-uart  	rm -f usrp-e-uart-rx  	rm -f usrp-e-led  	rm -f usrp-e-ctl  	rm -f usrp-e-button -	rm -f fpga-downloader  	rm -f usrp-e-gpio  	rm -f usrp-e-debug-pins  	rm -f usrp-e-lb-test -	rm -f usrp-e-crc-rw -	rm -f clkgen-config diff --git a/host/apps/omap_debug/clkgen-config.cc b/host/apps/omap_debug/clkgen-config.cc deleted file mode 100644 index e8279b4ae..000000000 --- a/host/apps/omap_debug/clkgen-config.cc +++ /dev/null @@ -1,296 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2004,2008,2009 Free Software Foundation, Inc. - * - * This file is part of UHD - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. -*/ - -#include <iostream> -#include <sstream> -#include <fstream> -#include <string> -#include <cstdlib> - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <linux/spi/spidev.h> - - -// Programming data for clock gen chip -static const unsigned int config_data[] = { -	0x000024, -	0x023201, -	0x000081, -	0x000400, -	0x00104c, -	0x001101, -	0x001200, -	0x001300, -	0x001414, -	0x001500, -	0x001604, -	0x001704, -	0x001807, -	0x001900, -	//0x001a00,//for debug -	0x001a32, -	0x001b12, -	0x001c44, -	0x001d00, -	0x001e00, -	0x00f062, -	0x00f162, -	0x00f262, -	0x00f362, -	0x00f462, -	0x00f562, -	0x00f662, -	0x00f762, -	0x00f862, -	0x00f962, -	0x00fa62, -	0x00fb62, -	0x00fc00, -	0x00fd00, -	0x019021, -	0x019100, -	0x019200, -	0x019333, -	0x019400, -	0x019500, -	0x019611, -	0x019700, -	0x019800, -	0x019900, -	0x019a00, -	0x019b00, -	0x01e003, -	0x01e102, -	0x023000, -	0x023201, -	0x0b0201, -	0x0b0300, -	0x001fff, -	0x0a0000, -	0x0a0100, -	0x0a0200, -	0x0a0302, -	0x0a0400, -	0x0a0504, -	0x0a060e, -	0x0a0700, -	0x0a0810, -	0x0a090e, -	0x0a0a00, -	0x0a0bf0, -	0x0a0c0b, -	0x0a0d01, -	0x0a0e90, -	0x0a0f01, -	0x0a1001, -	0x0a11e0, -	0x0a1201, -	0x0a1302, -	0x0a1430, -	0x0a1580, -	0x0a16ff, -	0x023201, -	0x0b0301, -	0x023201, -}; - - -const unsigned int CLKGEN_SELECT = 145; - - -enum gpio_direction {IN, OUT}; - -class gpio { -	public: - -	gpio(unsigned int gpio_num, gpio_direction pin_direction, bool close_action); -	~gpio(); - -	bool get_value(); -	void set_value(bool state); - -	private: - -	unsigned int gpio_num; - -	std::stringstream base_path; -	std::fstream value_file; -	std::fstream direction_file; -	bool close_action; // True set to input and release, false do nothing -}; - -class spidev { -	public: - -	spidev(std::string dev_name); -	~spidev(); - -	void send(char *wbuf, char *rbuf, unsigned int nbytes); - -	private: - -	int fd; - -}; - -gpio::gpio(unsigned int _gpio_num, gpio_direction pin_direction, bool close_action) -{ -	std::fstream export_file; - -	gpio_num = _gpio_num; - -	export_file.open("/sys/class/gpio/export", std::ios::out); -	if (!export_file.is_open())  ///\todo Poor error handling -		std::cout << "Failed to open gpio export file." << std::endl; - -	export_file << gpio_num << std::endl; - -	base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; - -	std::string direction_file_name; - -	direction_file_name = base_path.str() + "/direction"; - -	direction_file.open(direction_file_name.c_str());  -	if (!direction_file.is_open()) -		std::cout << "Failed to open direction file." << std::endl; -	if (pin_direction == OUT) -		direction_file << "out" << std::endl; -	else -		direction_file << "in" << std::endl; - -	std::string value_file_name; - -	value_file_name = base_path.str() + "/value"; - -	value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); -	if (!value_file.is_open()) -		std::cout << "Failed to open value file." << std::endl; -} - -bool gpio::get_value() -{ - -	std::string val; - -	std::getline(value_file, val); -	value_file.seekg(0); - -	if (val == "0") -		return false; -	else if (val == "1") -		return true; -	else -		std::cout << "Data read from value file|" << val << "|" << std::endl; - -	return false; -} - -void gpio::set_value(bool state) -{ - -	if (state) -		value_file << "1" << std::endl; -	else -		value_file << "0" << std::endl; -} - -gpio::~gpio() -{ -	if (close_action) { -		std::fstream unexport_file; - -		direction_file << "in" << std::endl; - -		unexport_file.open("/sys/class/gpio/unexport", std::ios::out); -		if (!unexport_file.is_open())  ///\todo Poor error handling -			std::cout << "Failed to open gpio export file." << std::endl; - -		unexport_file << gpio_num << std::endl; -		 -	 } - -} - -spidev::spidev(std::string fname) -{ -	int ret; -	int mode = 0; -	int speed = 12000; -	int bits = 24; - -	fd = open(fname.c_str(), O_RDWR); - -	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); -	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); -	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); -} -	 - -spidev::~spidev() -{ -	close(fd); -} - -void spidev::send(char *buf, char *rbuf, unsigned int nbytes) -{ -	int ret; - -	struct spi_ioc_transfer tr; -	tr.tx_buf = (unsigned long) buf; -	tr.rx_buf = (unsigned long) rbuf; -	tr.len = nbytes; -	tr.delay_usecs = 0; -	tr.speed_hz = 12000000; -	tr.bits_per_word = 24; - -	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);	 - -} - -static void send_config_to_clkgen(gpio &chip_select, const unsigned int data[], unsigned int data_size) -{ -	spidev spi("/dev/spidev1.0"); -	unsigned int rbuf; - -	for (unsigned int i = 0; i < data_size; i++) { - -		std::cout << "sending " << std::hex << data[i] << std::endl; -		chip_select.set_value(0); -		spi.send((char *)&data[i], (char *)&rbuf, 4); -		chip_select.set_value(1); - -	}; -} - -int main(int argc, char *argv[]) -{ - -	gpio clkgen_select(CLKGEN_SELECT, OUT, true); - -	send_config_to_clkgen(clkgen_select, config_data, sizeof(config_data)/sizeof(unsigned int)); -} - diff --git a/host/apps/omap_debug/fpga-downloader.cc b/host/apps/omap_debug/fpga-downloader.cc deleted file mode 100644 index 4e475b5c1..000000000 --- a/host/apps/omap_debug/fpga-downloader.cc +++ /dev/null @@ -1,253 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2004,2008,2009 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. -*/ - -#include <iostream> -#include <sstream> -#include <fstream> -#include <string> -#include <cstdlib> - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <linux/spi/spidev.h> - -/* - * Configuration connections - * - * CCK    - MCSPI1_CLK - * DIN    - MCSPI1_MOSI - * PROG_B - GPIO_175     - output (change mux) - * DONE   - GPIO_173     - input  (change mux) - * INIT_B - GPIO_114     - input  (change mux) - * -*/ - -const unsigned int PROG_B = 175; -const unsigned int DONE   = 173; -const unsigned int INIT_B = 114; - -static std::string bit_file = "safe_u1e.bin"; - -const int BUF_SIZE = 4096; - -enum gpio_direction {IN, OUT}; - -class gpio { -	public: - -	gpio(unsigned int gpio_num, gpio_direction pin_direction); - -	bool get_value(); -	void set_value(bool state); - -	private: - -	std::stringstream base_path; -	std::fstream value_file;	 -}; - -class spidev { -	public: - -	spidev(std::string dev_name); -	~spidev(); - -	void send(char *wbuf, char *rbuf, unsigned int nbytes); - -	private: - -	int fd; - -}; - -gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) -{ -	std::fstream export_file; - -	export_file.open("/sys/class/gpio/export", std::ios::out); -	if (!export_file.is_open())  ///\todo Poor error handling -		std::cout << "Failed to open gpio export file." << std::endl; - -	export_file << gpio_num << std::endl; - -	base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; - -	std::fstream direction_file; -	std::string direction_file_name; - -	if (gpio_num != 114) { -		direction_file_name = base_path.str() + "/direction"; - -		direction_file.open(direction_file_name.c_str());  -		if (!direction_file.is_open()) -			std::cout << "Failed to open direction file." << std::endl; -		if (pin_direction == OUT) -			direction_file << "out" << std::endl; -		else -			direction_file << "in" << std::endl; -	} - -	std::string value_file_name; - -	value_file_name = base_path.str() + "/value"; - -	value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); -	if (!value_file.is_open()) -		std::cout << "Failed to open value file." << std::endl; -} - -bool gpio::get_value() -{ - -	std::string val; - -	std::getline(value_file, val); -	value_file.seekg(0); - -	if (val == "0") -		return false; -	else if (val == "1") -		return true; -	else -		std::cout << "Data read from value file|" << val << "|" << std::endl; - -	return false; -} - -void gpio::set_value(bool state) -{ - -	if (state) -		value_file << "1" << std::endl; -	else -		value_file << "0" << std::endl; -} - -static void prepare_fpga_for_configuration(gpio &prog, gpio &init) -{ - -	prog.set_value(true); -	prog.set_value(false); -	prog.set_value(true); - -#if 0 -	bool ready_to_program(false); -	unsigned int count(0); -	do { -		ready_to_program = init.get_value(); -		count++; - -		sleep(1); -	} while (count < 10 && !ready_to_program); - -	if (count == 10) { -		std::cout << "FPGA not ready for programming." << std::endl; -		exit(-1); -	} -#endif -} - -spidev::spidev(std::string fname) -{ -	int ret; -	int mode = 0; -	int speed = 12000000; -	int bits = 8; - -	fd = open(fname.c_str(), O_RDWR); - -	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); -	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); -	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); -} -	 - -spidev::~spidev() -{ -	close(fd); -} - -void spidev::send(char *buf, char *rbuf, unsigned int nbytes) -{ -	int ret; - -	struct spi_ioc_transfer tr; -	tr.tx_buf = (unsigned long) buf; -	tr.rx_buf = (unsigned long) rbuf; -	tr.len = nbytes; -	tr.delay_usecs = 0; -	tr.speed_hz = 48000000; -	tr.bits_per_word = 8; - -	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);	 - -} - -static void send_file_to_fpga(std::string &file_name, gpio &error, gpio &done) -{ -	std::ifstream bitstream; - -	std::cout << "File name - " << file_name.c_str() << std::endl; - -	bitstream.open(file_name.c_str(), std::ios::binary); -	if (!bitstream.is_open()) -		std::cout << "File " << file_name << " not opened succesfully." << std::endl; - -	spidev spi("/dev/spidev1.0"); -	char buf[BUF_SIZE]; -	char rbuf[BUF_SIZE]; - -	do { -		bitstream.read(buf, BUF_SIZE); -		spi.send(buf, rbuf, bitstream.gcount()); - -		if (error.get_value()) -			std::cout << "INIT_B went high, error occured." << std::endl; - -		if (!done.get_value()) -			std::cout << "Configuration complete." << std::endl; - -	} while (bitstream.gcount() == BUF_SIZE); -} - -int main(int argc, char *argv[]) -{ - -	gpio gpio_prog_b(PROG_B, OUT); -	gpio gpio_init_b(INIT_B, IN); -	gpio gpio_done  (DONE,   IN); - -	if (argc == 2) -		bit_file = argv[1]; - -	std::cout << "FPGA config file: " << bit_file << std::endl; - -	prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); - -	std::cout << "Done = " << gpio_done.get_value() << std::endl; - -	send_file_to_fpga(bit_file, gpio_init_b, gpio_done); -} - diff --git a/host/apps/omap_debug/usrp-e-loopback.c b/host/apps/omap_debug/usrp-e-loopback.c deleted file mode 100644 index d11cf7d09..000000000 --- a/host/apps/omap_debug/usrp-e-loopback.c +++ /dev/null @@ -1,194 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/mman.h> -#include "usrp_e.h" - -// max length #define PKT_DATA_LENGTH 1016 -static int packet_data_length; -static int error; - -struct pkt { -	int len; -	int checksum; -	int seq_num; -	short data[]; -}; - -static int fp; - -static int calc_checksum(struct pkt *p) -{ -	int i, sum; - -	i = 0; -	sum = 0; - -	for (i=0; i < p->len; i++) -		sum += p->data[i]; - -	sum += p->seq_num; -	sum += p->len; - -	return sum; -} - -static void *read_thread(void *threadid) -{ -	char *rx_data; -	int cnt, prev_seq_num, pkt_count, seq_num_failure; -	struct pkt *p; -	unsigned long bytes_transfered, elapsed_seconds; -	struct timeval start_time, finish_time; - -	printf("Greetings from the reading thread!\n"); - -	bytes_transfered = 0; -	gettimeofday(&start_time, NULL); - -	// IMPORTANT: must assume max length packet from fpga -	rx_data = malloc(2048); -	p = (struct pkt *) ((void *)rx_data); - -	prev_seq_num = 0; -	pkt_count = 0; -	seq_num_failure = 0; - -	while (1) { - -		cnt = read(fp, rx_data, 2048); -		if (cnt < 0) -			printf("Error returned from read: %d, sequence number = %d\n", cnt, p->seq_num); - -//		printf("p->seq_num = %d\n", p->seq_num); - - -		pkt_count++; - -		if (p->seq_num != prev_seq_num + 1) { -			printf("Sequence number fail, current = %d, previous = %d, pkt_count = %d\n", -				p->seq_num, prev_seq_num, pkt_count); - -			seq_num_failure ++; -			if (seq_num_failure > 2) -				error = 1; -		} - -		prev_seq_num = p->seq_num; - -		if (calc_checksum(p) != p->checksum) { -			printf("Checksum fail packet = %X, expected = %X, pkt_count = %d\n", -				calc_checksum(p), p->checksum, pkt_count); -			error = 1; -		} - -		bytes_transfered += cnt; - -		if (bytes_transfered > (100 * 1000000)) { -			gettimeofday(&finish_time, NULL); -			elapsed_seconds = finish_time.tv_sec - start_time.tv_sec; - -			printf("RX data transfer rate = %f K Samples/second\n", -				(float) bytes_transfered / (float) elapsed_seconds / 4000); - - -			start_time = finish_time; -			bytes_transfered = 0; -		} - - -//		printf("."); -//		fflush(stdout); -//		printf("\n"); -	} - -} - -static void *write_thread(void *threadid) -{ -	int seq_number, i, cnt; -	void *tx_data; -	struct pkt *p; - -	printf("Greetings from the write thread!\n"); - -	tx_data = malloc(2048); -	p = (struct pkt *) ((void *)tx_data); - -	for (i=0; i < packet_data_length; i++) -//		p->data[i] = random() >> 16; -		p->data[i] = i; - -	seq_number = 1; - -	while (1) { -		p->seq_num = seq_number++; - -		if (packet_data_length > 0) -			p->len = packet_data_length; -		else -			p->len = (random() & 0x1ff) + (1004 - 512); - -		p->checksum = calc_checksum(p); - -		cnt = write(fp, tx_data, p->len * 2 + 12); -		if (cnt < 0) -			printf("Error returned from write: %d\n", cnt); -//		sleep(1); -	} -} - - -int main(int argc, char *argv[]) -{ -	pthread_t tx, rx; -	long int t; -	struct sched_param s = { -		.sched_priority = 1 -	}; -	void *rb; -	struct usrp_transfer_frame *tx_rb, *rx_rb; - -	if (argc < 2) { -		printf("%s data_size\n", argv[0]); -		return -1; -	} - -	packet_data_length = atoi(argv[1]); - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	rb = mmap(0, 202 * 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fp, 0); -	if (!rb) { -		printf("mmap failed\n"); -		exit; -	} - - -	sched_setscheduler(0, SCHED_RR, &s); -	error = 0; - -#if 1 -	if (pthread_create(&rx, NULL, read_thread, (void *) t)) { -		printf("Failed to create rx thread\n"); -		exit(-1); -	} - -	sleep(1); -#endif - -	if (pthread_create(&tx, NULL, write_thread, (void *) t)) { -		printf("Failed to create tx thread\n"); -		exit(-1); -	} - -//	while (!error) -		sleep(1000000000); - -	printf("Done sleeping\n"); -} diff --git a/host/apps/omap_debug/usrp-e-mm-loopback.c b/host/apps/omap_debug/usrp-e-mm-loopback.c deleted file mode 100644 index b67eecd21..000000000 --- a/host/apps/omap_debug/usrp-e-mm-loopback.c +++ /dev/null @@ -1,260 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include <sys/mman.h> -#include <poll.h> -#include "usrp_e.h" - -// max length #define PKT_DATA_LENGTH 1016 -static int packet_data_length; -static int error; - -struct pkt { -	int len; -	int checksum; -	int seq_num; -	short data[1024-6]; -}; - -struct ring_buffer_info (*rxi)[]; -struct ring_buffer_info (*txi)[]; -struct pkt (*rx_buf)[200]; -struct pkt (*tx_buf)[200]; - -static int fp; -static struct usrp_e_ring_buffer_size_t rb_size; - -static int calc_checksum(struct pkt *p) -{ -	int i, sum; - -	i = 0; -	sum = 0; - -	for (i=0; i < p->len; i++) -		sum += p->data[i]; - -	sum += p->seq_num; -	sum += p->len; - -	return sum; -} - -static void *read_thread(void *threadid) -{ -	int cnt, prev_seq_num, pkt_count, seq_num_failure; -	struct pkt *p; -	unsigned long bytes_transfered, elapsed_seconds; -	struct timeval start_time, finish_time; -	int rb_read; - -	printf("Greetings from the reading thread!\n"); -	printf("sizeof pkt = %d\n", sizeof(struct pkt)); - -	rb_read = 0; - -	bytes_transfered = 0; -	gettimeofday(&start_time, NULL); - -	prev_seq_num = 0; -	pkt_count = 0; -	seq_num_failure = 0; - -	while (1) { - -		if (!((*rxi)[rb_read].flags & RB_USER)) { -//			printf("Waiting for data\n"); -			struct pollfd pfd; -			pfd.fd = fp; -			pfd.events = POLLIN; -			ssize_t ret = poll(&pfd, 1, -1); -		} - -		(*rxi)[rb_read].flags = RB_USER_PROCESS; - -//		printf("pkt received, rb_read = %d\n", rb_read); - -		cnt = (*rxi)[rb_read].len; -		p = &(*rx_buf)[rb_read]; - -//		cnt = read(fp, rx_data, 2048); -//		if (cnt < 0) -//			printf("Error returned from read: %d, sequence number = %d\n", cnt, p->seq_num); - -//		printf("p = %X, p->seq_num = %d p->len = %d\n", p, p->seq_num, p->len); - - -		pkt_count++; - -		if (p->seq_num != prev_seq_num + 1) { -			printf("Sequence number fail, current = %d, previous = %d, pkt_count = %d\n", -				p->seq_num, prev_seq_num, pkt_count); -			printf("pkt received, rb_read = %d\n", rb_read); -			printf("p = %X, p->seq_num = %d p->len = %d\n", p, p->seq_num, p->len); - -			seq_num_failure ++; -			if (seq_num_failure > 2) -				error = 1; -		} - -		prev_seq_num = p->seq_num; - -		if (calc_checksum(p) != p->checksum) { -			printf("Checksum fail packet = %X, expected = %X, pkt_count = %d\n", -				calc_checksum(p), p->checksum, pkt_count); -			error = 1; -		} - -		(*rxi)[rb_read].flags = RB_KERNEL; - -		rb_read++; -		if (rb_read == rb_size.num_rx_frames) -			rb_read = 0; - -		bytes_transfered += cnt; - -		if (bytes_transfered > (100 * 1000000)) { -			gettimeofday(&finish_time, NULL); -			elapsed_seconds = finish_time.tv_sec - start_time.tv_sec; - -			printf("RX data transfer rate = %f K Samples/second\n", -				(float) bytes_transfered / (float) elapsed_seconds / 4000); - - -			start_time = finish_time; -			bytes_transfered = 0; -		} - - -//		printf("."); -//		fflush(stdout); -//		printf("\n"); -	} - -} - -static void *write_thread(void *threadid) -{ -	int seq_number, i, cnt, rb_write; -	void *tx_data; -	struct pkt *p; - -	printf("Greetings from the write thread!\n"); - -	tx_data = malloc(2048); -	p = (struct pkt *) ((void *)tx_data); - -	for (i=0; i < packet_data_length; i++) -//		p->data[i] = random() >> 16; -		p->data[i] = i; - -	seq_number = 1; -	rb_write = 0; - -	while (1) { -		p->seq_num = seq_number++; - -		if (packet_data_length > 0) -			p->len = packet_data_length; -		else -			p->len = (random() & 0x1ff) + (1004 - 512); - -		p->checksum = calc_checksum(p); - -		if (!((*txi)[rb_write].flags & RB_KERNEL)) { -//			printf("Waiting for space\n"); -			struct pollfd pfd; -			pfd.fd = fp; -			pfd.events = POLLOUT; -			ssize_t ret = poll(&pfd, 1, -1); -		} - -		memcpy(&(*tx_buf)[rb_write], tx_data, p->len * 2 + 12); - -		(*txi)[rb_write].len = p->len * 2 + 12; -		(*txi)[rb_write].flags = RB_USER; - -		rb_write++; -		if (rb_write == rb_size.num_tx_frames) -			rb_write = 0; - -		cnt = write(fp, NULL, 0); -//		if (cnt < 0) -//			printf("Error returned from write: %d\n", cnt); -//		sleep(1); -	} -} - - -int main(int argc, char *argv[]) -{ -	pthread_t tx, rx; -	long int t; -	struct sched_param s = { -		.sched_priority = 1 -	}; -	int ret, map_size, page_size; -	void *rb; - -	if (argc < 2) { -		printf("%s data_size\n", argv[0]); -		return -1; -	} - -	packet_data_length = atoi(argv[1]); - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	page_size = getpagesize(); - -	ret = ioctl(fp, USRP_E_GET_RB_INFO, &rb_size); - -	map_size = (rb_size.num_pages_rx_flags + rb_size.num_pages_tx_flags) * page_size + -		(rb_size.num_rx_frames + rb_size.num_tx_frames) * (page_size >> 1); - -	rb = mmap(0, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fp, 0); -	if (rb == MAP_FAILED) { -		perror("mmap failed"); -		return -1; -	} - -	printf("rb = %X\n", rb); - -	rxi = rb; -	rx_buf = rb + (rb_size.num_pages_rx_flags * page_size); -	txi = rb +  (rb_size.num_pages_rx_flags * page_size) + -		(rb_size.num_rx_frames * page_size >> 1); -	tx_buf = rb +  (rb_size.num_pages_rx_flags * page_size) + -		(rb_size.num_rx_frames * page_size >> 1) + -		(rb_size.num_pages_tx_flags * page_size); - -	printf("rxi = %X, rx_buf = %X, txi = %X, tx_buf = %X\n", rxi, rx_buf, txi, tx_buf); - -	sched_setscheduler(0, SCHED_RR, &s); -	error = 0; - -#if 1 -	if (pthread_create(&rx, NULL, read_thread, (void *) t)) { -		printf("Failed to create rx thread\n"); -		exit(-1); -	} - -	sleep(1); -#endif - -	if (pthread_create(&tx, NULL, write_thread, (void *) t)) { -		printf("Failed to create tx thread\n"); -		exit(-1); -	} - -//	while (!error) -		sleep(1000000000); - -	printf("Done sleeping\n"); -} diff --git a/host/apps/omap_debug/usrp-e-random-loopback.c b/host/apps/omap_debug/usrp-e-random-loopback.c deleted file mode 100644 index 5960b8fbd..000000000 --- a/host/apps/omap_debug/usrp-e-random-loopback.c +++ /dev/null @@ -1,149 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include "usrp_e.h" - -// max length #define PKT_DATA_LENGTH 1014 -static int packet_data_length; - -struct pkt { -	int checksum; -	int seq_num; -	int len; -	short data[]; -}; - -static int fp; - -static int calc_checksum(struct pkt *p) -{ -	int i, sum; - -	i = 0; -	sum = 0; - -	for (i=0; i < p->len; i++) -		sum += p->data[i]; - -	sum += p->seq_num; - -	return sum; -} - -int randN(int n) -{ -	long tmp; - -	tmp = rand()  % n; - -	return tmp; -} - -static void *read_thread(void *threadid) -{ -	int cnt, prev_seq_num; -	struct usrp_transfer_frame *rx_data; -	struct pkt *p; - -	printf("Greetings from the reading thread!\n"); - -	// IMPORTANT: must assume max length packet from fpga -	rx_data = malloc(sizeof(struct usrp_transfer_frame) + sizeof(struct pkt) + (1014 * 2)); -	rx_data = malloc(2048); -	p = (struct pkt *) ((void *)rx_data + offsetof(struct usrp_transfer_frame, buf)); -	//p = &(rx_data->buf[0]); -	printf("Address of rx_data = %p, p = %p\n", rx_data, p); -	printf("offsetof = %d\n", offsetof(struct usrp_transfer_frame, buf)); -	printf("sizeof rx data = %d\n", sizeof(struct usrp_transfer_frame) + sizeof(struct pkt)); - -	prev_seq_num = 0; - -	while (1) { - -		cnt = read(fp, rx_data, 2048); -//		printf("Packet received, status = %X, len = %d\n", rx_data->status, rx_data->len); -//		printf("p->seq_num = %d\n", p->seq_num); - -		if (p->seq_num != prev_seq_num + 1) -			printf("Sequence number fail, current = %d, previous = %d\n", -				p->seq_num, prev_seq_num); -		prev_seq_num = p->seq_num; - -		if (calc_checksum(p) != p->checksum) -			printf("Checksum fail packet = %d, expected = %d\n", -				calc_checksum(p), p->checksum); -		printf("."); -		fflush(stdout); -//		printf("\n"); -	} - -} - -static void *write_thread(void *threadid) -{ -	int seq_number, i, cnt, pkt_cnt; -	struct usrp_transfer_frame *tx_data; -	struct pkt *p; - -	printf("Greetings from the write thread!\n"); - -	// Allocate max length buffer for frame -	tx_data = malloc(2048); -	p = (struct pkt *) ((void *)tx_data + offsetof(struct usrp_transfer_frame, buf)); -	printf("Address of tx_data = %p, p = %p\n", tx_data, p); - -	printf("sizeof rp_transfer_frame = %d, sizeof pkt = %d\n", sizeof(struct usrp_transfer_frame), sizeof(struct pkt)); - -	for (i=0; i < 1014; i++) -//		p->data[i] = random() >> 16; -		p->data[i] = i; - -	tx_data->status = 0xdeadbeef; -	tx_data->len = 8 + packet_data_length * 2; - -	printf("tx_data->len = %d\n", tx_data->len); - -	seq_number = 1; - -	while (1) { -		pkt_cnt = randN(16); -		for (i = 0; i < pkt_cnt; i++) { -			p->seq_num = seq_number++; -			p->len = randN(1013) + 1; -			p->checksum = calc_checksum(p); -			tx_data->len = 12 + p->len * 2; -			cnt = write(fp, tx_data, tx_data->len + 8); -		} -		sleep(random() >> 31); -	} -} - - -int main(int argc, char *argv[]) -{ -	pthread_t tx, rx; -	long int t; - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	if (pthread_create(&rx, NULL, read_thread, (void *) t)) { -		printf("Failed to create rx thread\n"); -		exit(-1); -	} - -	sleep(1); - -	if (pthread_create(&tx, NULL, write_thread, (void *) t)) { -		printf("Failed to create tx thread\n"); -		exit(-1); -	} - -	sleep(1000000000); - -	printf("Done sleeping\n"); -} diff --git a/host/apps/omap_debug/usrp-e-timed.c b/host/apps/omap_debug/usrp-e-timed.c deleted file mode 100644 index 3cb33ce2d..000000000 --- a/host/apps/omap_debug/usrp-e-timed.c +++ /dev/null @@ -1,233 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> -#include <stddef.h> -#include "usrp_e.h" - -// max length #define PKT_DATA_LENGTH 1016 -static int packet_data_length; - -struct pkt { -	int checksum; -	int seq_num; -	short data[]; -}; - -static int fp; - -static int calc_checksum(struct pkt *p) -{ -	int i, sum; - -	i = 0; -	sum = 0; - -	for (i=0; i < packet_data_length; i++) -		sum += p->data[i]; - -	sum += p->seq_num; - -	return sum; -} - -static void *read_thread(void *threadid) -{ -	int cnt, prev_seq_num; -	struct usrp_transfer_frame *rx_data; -	struct pkt *p; -	int rx_pkt_cnt; -	int i; -	unsigned long bytes_transfered, elapsed_seconds; -	struct timeval start_time, finish_time; - -	printf("Greetings from the reading thread!\n"); - -	bytes_transfered = 0; -	gettimeofday(&start_time, NULL); - -	// IMPORTANT: must assume max length packet from fpga -	rx_data = malloc(sizeof(struct usrp_transfer_frame) + sizeof(struct pkt) + (1016 * 2)); -	p = (struct pkt *) ((void *)rx_data + offsetof(struct usrp_transfer_frame, buf)); -	//p = &(rx_data->buf[0]); -	printf("Address of rx_data = %p, p = %p\n", rx_data, p); -	printf("offsetof = %d\n", offsetof(struct usrp_transfer_frame, buf)); -	printf("sizeof rx data = %d\n", sizeof(struct usrp_transfer_frame) + sizeof(struct pkt)); - -	prev_seq_num = 0; - -	rx_pkt_cnt = 0; - -	while (1) { - -		cnt = read(fp, rx_data, 2048); -		if (cnt < 0) -			printf("Error returned from read: %d\n", cnt); -		rx_pkt_cnt++; - -#if 0 -		if (rx_pkt_cnt  == 512) { -			printf("."); -			fflush(stdout); -			rx_pkt_cnt = 0; -		} -#endif - -		if (rx_data->status & RB_OVERRUN) -			printf("O"); - -		bytes_transfered += rx_data->len; - -		if (bytes_transfered > (100 * 1000000)) { -			gettimeofday(&finish_time, NULL); -			elapsed_seconds = finish_time.tv_sec - start_time.tv_sec; - -			printf("RX data transfer rate = %f K Samples/second\n", -				(float) bytes_transfered / (float) elapsed_seconds / 4000); - - -			start_time = finish_time; -			bytes_transfered = 0; -                } -	} - -} - -static void *write_thread(void *threadid) -{ -	int seq_number, i, cnt, tx_pkt_cnt; -	struct usrp_transfer_frame *tx_data; -	struct pkt *p; -	unsigned long bytes_transfered, elapsed_seconds; -	struct timeval start_time, finish_time; - -	printf("Greetings from the write thread!\n"); - -	bytes_transfered = 0; -	gettimeofday(&start_time, NULL); - -	tx_data = malloc(sizeof(struct usrp_transfer_frame) + sizeof(struct pkt) + (packet_data_length * 2)); -	p = (struct pkt *) ((void *)tx_data + offsetof(struct usrp_transfer_frame, buf)); -	printf("Address of tx_data = %p, p = %p\n", tx_data, p); - -	printf("sizeof rp_transfer_frame = %d, sizeof pkt = %d\n", sizeof(struct usrp_transfer_frame), sizeof(struct pkt)); - -	for (i=0; i < packet_data_length; i++) -//		p->data[i] = random() >> 16; -		p->data[i] = i; - -	tx_data->status = 0; -	tx_data->len = 8 + packet_data_length * 2; - -	printf("tx_data->len = %d\n", tx_data->len); - -	seq_number = 1; -	tx_pkt_cnt = 0; - -	while (1) { - -		tx_pkt_cnt++; - -#if 0 -		if (tx_pkt_cnt  == 512) { -			printf("."); -			fflush(stdout); -		} -		if (tx_pkt_cnt  == 1024) { -			printf("'"); -			fflush(stdout); -		} -		if (tx_pkt_cnt  == 1536) { -			printf(":"); -			fflush(stdout); -			tx_pkt_cnt = 0; -		} -#endif - -//		printf("tx status = %X, len = %d\n", tx_data->status, tx_data->len); -		p->seq_num = seq_number++; -		p->checksum = calc_checksum(p); -		cnt = write(fp, tx_data, 2048); -		if (cnt < 0) -			printf("Error returned from write: %d\n", cnt); - -		bytes_transfered += tx_data->len; - -		if (bytes_transfered > (100 * 1000000)) { -			gettimeofday(&finish_time, NULL); -			elapsed_seconds = finish_time.tv_sec - start_time.tv_sec; - -			printf("TX data transfer rate = %f K Samples/second\n", -				(float) bytes_transfered / (float) elapsed_seconds / 4000); - - -			start_time = finish_time; -			bytes_transfered = 0; -                } -//		sleep(1); -	} -} - - -int main(int argc, char *argv[]) -{ -	pthread_t tx, rx; -	long int t; -	int fpga_config_flag ,decimation; -	struct usrp_e_ctl16 d; -	struct sched_param s = { -		.sched_priority = 1 -	}; - -	if (argc < 4) { -		printf("%s r|w|rw decimation data_size\n", argv[0]); -		return -1; -	} - -	decimation = atoi(argv[2]); -	packet_data_length = atoi(argv[3]); - -	fp = open("/dev/usrp_e0", O_RDWR); -	printf("fp = %d\n", fp); - -	fpga_config_flag = 0; -	if (strcmp(argv[1], "w") == 0) -		fpga_config_flag |= (1 << 15); -	else if (strcmp(argv[1], "r") == 0) -		fpga_config_flag |= (1 << 14); -	else if (strcmp(argv[1], "rw") == 0) -		fpga_config_flag |= ((1 << 15) | (1 << 14)); - -	fpga_config_flag |= decimation; - -	d.offset = 14; -	d.count = 1; -	d.buf[0] = fpga_config_flag; -	ioctl(fp, USRP_E_WRITE_CTL16, &d); - -	sleep(1); // in case the kernel threads need time to start. FIXME if so - -	sched_setscheduler(0, SCHED_RR, &s); - -	if (fpga_config_flag & (1 << 14)) { -		if (pthread_create(&rx, NULL, read_thread, (void *) t)) { -			printf("Failed to create rx thread\n"); -			exit(-1); -		} -	} - -	sleep(1); - -	if (fpga_config_flag & (1 << 15)) { -		if (pthread_create(&tx, NULL, write_thread, (void *) t)) { -			printf("Failed to create tx thread\n"); -			exit(-1); -		} -	} - -	sleep(10000); - -	printf("Done sleeping\n"); -} 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/include/uhd/transport/if_addrs.hpp b/host/include/uhd/transport/if_addrs.hpp index c831750d7..689aff42c 100644 --- a/host/include/uhd/transport/if_addrs.hpp +++ b/host/include/uhd/transport/if_addrs.hpp @@ -31,7 +31,6 @@ namespace uhd{ namespace transport{          std::string inet;          std::string mask;          std::string bcast; -        if_addrs_t(void);      };      /*! diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index a98bcc14e..a5bf9c5f1 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -48,20 +48,31 @@ ENDIF(ENABLE_USB)  ########################################################################  MESSAGE(STATUS "")  MESSAGE(STATUS "Configuring interface address discovery...") - +INCLUDE(CheckCXXSourceCompiles)  INCLUDE(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H) + +CHECK_CXX_SOURCE_COMPILES(" +    #include <ifaddrs.h> +    int main(){ +        struct ifaddrs *ifap; +        getifaddrs(&ifap); +        return 0; +    } +    " HAVE_GETIFADDRS +) +  CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H) -IF(HAVE_IFADDRS_H) +IF(HAVE_GETIFADDRS)      MESSAGE(STATUS "  Interface address discovery supported through getifaddrs.") -    SET(IF_ADDRS_DEFS HAVE_IFADDRS_H) +    SET(IF_ADDRS_DEFS HAVE_GETIFADDRS)  ELSEIF(HAVE_WINSOCK2_H)      MESSAGE(STATUS "  Interface address discovery supported through SIO_GET_INTERFACE_LIST.") -    SET(IF_ADDRS_DEFS HAVE_WINSOCK2_H) -ELSE(HAVE_IFADDRS_H) +    SET(IF_ADDRS_DEFS HAVE_SIO_GET_INTERFACE_LIST) +ELSE()      MESSAGE(STATUS "  Interface address discovery not supported.") -ENDIF(HAVE_IFADDRS_H) +    SET(IF_ADDRS_DEFS HAVE_IF_ADDRS_DUMMY) +ENDIF()  SET_SOURCE_FILES_PROPERTIES(      ${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp @@ -80,6 +91,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/if_addrs.cpp b/host/lib/transport/if_addrs.cpp index 17cf8455b..b7c8ad844 100644 --- a/host/lib/transport/if_addrs.cpp +++ b/host/lib/transport/if_addrs.cpp @@ -20,14 +20,10 @@  #include <boost/cstdint.hpp>  #include <iostream> -uhd::transport::if_addrs_t::if_addrs_t(void){ -    /* NOP */ -} -  /***********************************************************************   * Interface address discovery through ifaddrs api   **********************************************************************/ -#if defined(HAVE_IFADDRS_H) +#ifdef HAVE_GETIFADDRS  #include <ifaddrs.h>  static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){ @@ -59,10 +55,12 @@ std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){      return if_addrs;  } +#endif /* HAVE_GETIFADDRS */ +  /***********************************************************************   * Interface address discovery through windows api   **********************************************************************/ -#elif defined(HAVE_WINSOCK2_H) +#ifdef HAVE_SIO_GET_INTERFACE_LIST  #include <winsock2.h>  std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){ @@ -98,13 +96,15 @@ std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){      return if_addrs;  } +#endif /* HAVE_SIO_GET_INTERFACE_LIST */ +  /***********************************************************************   * Interface address discovery not included   **********************************************************************/ -#else /* HAVE_IFADDRS_H */ +#ifdef HAVE_IF_ADDRS_DUMMY  std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){      return std::vector<if_addrs_t>();  } -#endif /* HAVE_IFADDRS_H */ +#endif /* HAVE_IF_ADDRS_DUMMY */ 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/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index 743528189..a4d3b2db2 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -24,8 +24,8 @@  ########################################################################  MESSAGE(STATUS "")  MESSAGE(STATUS "Configuring priority scheduling...") -  INCLUDE(CheckCXXSourceCompiles) +  CHECK_CXX_SOURCE_COMPILES("      #include <pthread.h>      int main(){ @@ -52,9 +52,10 @@ IF(HAVE_PTHREAD_SETSCHEDPARAM)  ELSEIF(HAVE_WIN_SETTHREADPRIORITY)      MESSAGE(STATUS "  Priority scheduling supported through windows SetThreadPriority.")      SET(THREAD_PRIO_DEFS HAVE_WIN_SETTHREADPRIORITY) -ELSE(HAVE_PTHREAD_SETSCHEDPARAM) +ELSE()      MESSAGE(STATUS "  Priority scheduling not supported.") -ENDIF(HAVE_PTHREAD_SETSCHEDPARAM) +    SET(THREAD_PRIO_DEFS HAVE_THREAD_PRIO_DUMMY) +ENDIF()  SET_SOURCE_FILES_PROPERTIES(      ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp @@ -66,21 +67,39 @@ SET_SOURCE_FILES_PROPERTIES(  ########################################################################  MESSAGE(STATUS "")  MESSAGE(STATUS "Configuring module loading...") +INCLUDE(CheckCXXSourceCompiles) -INCLUDE(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H) -CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H) +SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS}) +CHECK_CXX_SOURCE_COMPILES(" +    #include <dlfcn.h> +    int main(){ +        dlopen(0, 0); +        return 0; +    } +    " HAVE_DLOPEN +) +UNSET(CMAKE_REQUIRED_LIBRARIES) + +CHECK_CXX_SOURCE_COMPILES(" +    #include <windows.h> +    int main(){ +        LoadLibrary(0); +        return 0; +    } +    " HAVE_LOAD_LIBRARY +) -IF(HAVE_DLFCN_H) +IF(HAVE_DLOPEN)      MESSAGE(STATUS "  Module loading supported through dlopen.") -    SET(LOAD_MODULES_DEFS HAVE_DLFCN_H) +    SET(LOAD_MODULES_DEFS HAVE_DLOPEN)      LIBUHD_APPEND_LIBS(${CMAKE_DL_LIBS}) -ELSEIF(HAVE_WINDOWS_H) +ELSEIF(HAVE_LOAD_LIBRARY)      MESSAGE(STATUS "  Module loading supported through LoadLibrary.") -    SET(LOAD_MODULES_DEFS HAVE_WINDOWS_H) -ELSE(HAVE_DLFCN_H) +    SET(LOAD_MODULES_DEFS HAVE_LOAD_LIBRARY) +ELSE()      MESSAGE(STATUS "  Module loading not supported.") -ENDIF(HAVE_DLFCN_H) +    SET(LOAD_MODULES_DEFS HAVE_LOAD_MODULES_DUMMY) +ENDIF()  SET_SOURCE_FILES_PROPERTIES(      ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp diff --git a/host/lib/utils/load_modules.cpp b/host/lib/utils/load_modules.cpp index 623d31eb6..fa9b22438 100644 --- a/host/lib/utils/load_modules.cpp +++ b/host/lib/utils/load_modules.cpp @@ -29,9 +29,8 @@ namespace fs = boost::filesystem;  /***********************************************************************   * Module Load Function   **********************************************************************/ -#if defined(HAVE_DLFCN_H) +#ifdef HAVE_DLOPEN  #include <dlfcn.h> -  static void load_module(const std::string &file_name){      if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){          throw std::runtime_error(str( @@ -39,10 +38,11 @@ static void load_module(const std::string &file_name){          ));      }  } +#endif /* HAVE_DLOPEN */ -#elif defined(HAVE_WINDOWS_H) -#include <windows.h> +#ifdef HAVE_LOAD_LIBRARY +#include <windows.h>  static void load_module(const std::string &file_name){      if (LoadLibrary(file_name.c_str()) == NULL){          throw std::runtime_error(str( @@ -50,16 +50,16 @@ static void load_module(const std::string &file_name){          ));      }  } +#endif /* HAVE_LOAD_LIBRARY */ -#else +#ifdef HAVE_LOAD_MODULES_DUMMY  static void load_module(const std::string &file_name){      throw std::runtime_error(str(          boost::format("Module loading not supported: Cannot load \"%s\"") % file_name      ));  } - -#endif +#endif /* HAVE_LOAD_MODULES_DUMMY */  /***********************************************************************   * Load Modules diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index 40b74f655..18f372ec0 100644 --- a/host/lib/utils/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp @@ -44,7 +44,7 @@ static void check_priority_range(float priority){  /***********************************************************************   * Pthread API to set priority   **********************************************************************/ -#if defined(HAVE_PTHREAD_SETSCHEDPARAM) +#ifdef HAVE_PTHREAD_SETSCHEDPARAM      #include <pthread.h>      void uhd::set_thread_priority(float priority, bool realtime){ @@ -67,11 +67,12 @@ static void check_priority_range(float priority){          int ret = pthread_setschedparam(pthread_self(), policy, &sp);          if (ret != 0) throw std::runtime_error("error in pthread_setschedparam");      } +#endif /* HAVE_PTHREAD_SETSCHEDPARAM */  /***********************************************************************   * Windows API to set priority   **********************************************************************/ -#elif defined(HAVE_WIN_SETTHREADPRIORITY) +#ifdef HAVE_WIN_SETTHREADPRIORITY      #include <windows.h>      void uhd::set_thread_priority(float priority, bool realtime){ @@ -93,13 +94,14 @@ static void check_priority_range(float priority){          if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0)              throw std::runtime_error("error in SetThreadPriority");      } +#endif /* HAVE_WIN_SETTHREADPRIORITY */  /***********************************************************************   * Unimplemented API to set priority   **********************************************************************/ -#else +#ifdef HAVE_LOAD_MODULES_DUMMY      void uhd::set_thread_priority(float, bool){          throw std::runtime_error("set thread priority not implemented");      } -#endif /* HAVE_PTHREAD_SETSCHEDPARAM */ +#endif /* HAVE_LOAD_MODULES_DUMMY */ diff --git a/host/usrp_e_utils/CMakeLists.txt b/host/usrp_e_utils/CMakeLists.txt index 5123af592..1ecd2ac46 100644 --- a/host/usrp_e_utils/CMakeLists.txt +++ b/host/usrp_e_utils/CMakeLists.txt @@ -34,6 +34,7 @@ IF(ENABLE_USRP_E_UTILS)      SET(usrp_e_utils_sources          usrp-e-utility.cpp          usrp-e-loopback.c +        usrp-e-timed.c          usrp-e-wb-test.cpp          usrp-e-debug-pins.c          usrp-e-i2c.c diff --git a/host/usrp_e_utils/usrp-e-loopback.c b/host/usrp_e_utils/usrp-e-loopback.c index 454d81ba7..a63882475 100644 --- a/host/usrp_e_utils/usrp-e-loopback.c +++ b/host/usrp_e_utils/usrp-e-loopback.c @@ -1,14 +1,18 @@  #include <stdio.h> +#include <string.h>  #include <sys/types.h> +#include <sys/ioctl.h>  #include <fcntl.h>  #include <pthread.h>  #include <stdlib.h>  #include <unistd.h>  #include <stddef.h>  #include <sys/mman.h> -#include <linux/usrp_e.h> +#include <sys/time.h> +#include <poll.h> +#include "linux/usrp_e.h" -#define MAX_PACKET_SIZE 1016 +// max length #define PKT_DATA_LENGTH 1016  static int packet_data_length;  static int error; @@ -16,34 +20,16 @@ struct pkt {  	int len;  	int checksum;  	int seq_num; -	short data[]; +	short data[1024-6];  }; -static int length_array[2048]; -static int length_array_tail = 0; -static int length_array_head = 0; - -pthread_mutex_t length_array_mutex; //gotta lock the index to keep it from getting hosed - -//yes this is a circular buffer that does not check empty -//no i don't want to hear about it -void push_length_array(int length) { -	pthread_mutex_lock(&length_array_mutex); -	if(length_array_tail > 2047) length_array_tail = 0; -	length_array[length_array_tail++] = length; -	pthread_mutex_unlock(&length_array_mutex); -} - -int pop_length_array(void) { -	int retval; -	pthread_mutex_lock(&length_array_mutex); -	if(length_array_head > 2047) length_array_head = 0; -	retval = length_array[length_array_head++]; -	pthread_mutex_unlock(&length_array_mutex); -	return retval; -} +struct ring_buffer_info (*rxi)[]; +struct ring_buffer_info (*txi)[]; +struct pkt (*rx_buf)[200]; +struct pkt (*tx_buf)[200];  static int fp; +static struct usrp_e_ring_buffer_size_t rb_size;  static int calc_checksum(struct pkt *p)  { @@ -53,43 +39,56 @@ static int calc_checksum(struct pkt *p)  	sum = 0;  	for (i=0; i < p->len; i++) -		sum ^= p->data[i]; +		sum += p->data[i]; -	sum ^= p->seq_num; -	sum ^= p->len; +	sum += p->seq_num; +	sum += p->len;  	return sum;  }  static void *read_thread(void *threadid)  { -	char *rx_data;  	int cnt, prev_seq_num, pkt_count, seq_num_failure;  	struct pkt *p;  	unsigned long bytes_transfered, elapsed_seconds;  	struct timeval start_time, finish_time; -	int expected_count; +	int rb_read;  	printf("Greetings from the reading thread!\n"); +	printf("sizeof pkt = %d\n", sizeof(struct pkt)); + +	rb_read = 0;  	bytes_transfered = 0;  	gettimeofday(&start_time, NULL); -	// IMPORTANT: must assume max length packet from fpga -	rx_data = malloc(2048); -	p = (struct pkt *) ((void *)rx_data); -  	prev_seq_num = 0;  	pkt_count = 0;  	seq_num_failure = 0;  	while (1) { -		cnt = read(fp, rx_data, 2048); -		if (cnt < 0) -			printf("Error returned from read: %d, sequence number = %d\n", cnt, p->seq_num); +		if (!((*rxi)[rb_read].flags & RB_USER)) { +//			printf("Waiting for data\n"); +			struct pollfd pfd; +			pfd.fd = fp; +			pfd.events = POLLIN; +			poll(&pfd, 1, -1); +		} + +		(*rxi)[rb_read].flags = RB_USER_PROCESS; -//		printf("p->seq_num = %d\n", p->seq_num); +//		printf("pkt received, rb_read = %d\n", rb_read); + +		cnt = (*rxi)[rb_read].len; +		p = &(*rx_buf)[rb_read]; + +//		cnt = read(fp, rx_data, 2048); +//		if (cnt < 0) +//			printf("Error returned from read: %d, sequence number = %d\n", cnt, p->seq_num); + +//		printf("p = %X, p->seq_num = %d p->len = %d\n", p, p->seq_num, p->len);  		pkt_count++; @@ -97,17 +96,14 @@ static void *read_thread(void *threadid)  		if (p->seq_num != prev_seq_num + 1) {  			printf("Sequence number fail, current = %d, previous = %d, pkt_count = %d\n",  				p->seq_num, prev_seq_num, pkt_count); +			printf("pkt received, rb_read = %d\n", rb_read); +			printf("p = %p, p->seq_num = %d p->len = %d\n", p, p->seq_num, p->len);  			seq_num_failure ++;  			if (seq_num_failure > 2)  				error = 1;  		} -		expected_count = pop_length_array()*2+12; -		if(cnt != expected_count) { -			printf("Received %d bytes, expected %d\n", cnt, expected_count); -		} -  		prev_seq_num = p->seq_num;  		if (calc_checksum(p) != p->checksum) { @@ -116,6 +112,12 @@ static void *read_thread(void *threadid)  			error = 1;  		} +		(*rxi)[rb_read].flags = RB_KERNEL; + +		rb_read++; +		if (rb_read == rb_size.num_rx_frames) +			rb_read = 0; +  		bytes_transfered += cnt;  		if (bytes_transfered > (100 * 1000000)) { @@ -135,12 +137,12 @@ static void *read_thread(void *threadid)  //		fflush(stdout);  //		printf("\n");  	} - +	return NULL;  }  static void *write_thread(void *threadid)  { -	int seq_number, i, cnt; +	int seq_number, i, cnt, rb_write;  	void *tx_data;  	struct pkt *p; @@ -154,6 +156,7 @@ static void *write_thread(void *threadid)  		p->data[i] = i;  	seq_number = 1; +	rb_write = 0;  	while (1) {  		p->seq_num = seq_number++; @@ -161,30 +164,46 @@ static void *write_thread(void *threadid)  		if (packet_data_length > 0)  			p->len = packet_data_length;  		else -			p->len = (random()<<1 & 0x1ff) + (1004 - 512); - -		push_length_array(p->len); +			p->len = (random() & 0x1ff) + (1004 - 512);  		p->checksum = calc_checksum(p); -		cnt = write(fp, tx_data, p->len * 2 + 12); -		if (cnt < 0) -			printf("Error returned from write: %d\n", cnt); +		if (!((*txi)[rb_write].flags & RB_KERNEL)) { +//			printf("Waiting for space\n"); +			struct pollfd pfd; +			pfd.fd = fp; +			pfd.events = POLLOUT; +			poll(&pfd, 1, -1); +		} + +		memcpy(&(*tx_buf)[rb_write], tx_data, p->len * 2 + 12); + +		(*txi)[rb_write].len = p->len * 2 + 12; +		(*txi)[rb_write].flags = RB_USER; + +		rb_write++; +		if (rb_write == rb_size.num_tx_frames) +			rb_write = 0; + +		cnt = write(fp, NULL, 0); +//		if (cnt < 0) +//			printf("Error returned from write: %d\n", cnt);  //		sleep(1);  	} +	return NULL;  }  int main(int argc, char *argv[])  {  	pthread_t tx, rx; -	pthread_mutex_init(&length_array_mutex, 0); -	long int t; +	long int t = 0;  	struct sched_param s = {  		.sched_priority = 1  	}; +	int ret, map_size, page_size;  	void *rb; -	struct usrp_transfer_frame *tx_rb, *rx_rb; +	struct usrp_e_ctl16 d;  	if (argc < 2) {  		printf("%s data_size\n", argv[0]); @@ -192,22 +211,43 @@ int main(int argc, char *argv[])  	}  	packet_data_length = atoi(argv[1]); -	if(packet_data_length > MAX_PACKET_SIZE) { -		printf("Packet size must be smaller than %i\n", MAX_PACKET_SIZE); -		exit(-1); -	}  	fp = open("/dev/usrp_e0", O_RDWR);  	printf("fp = %d\n", fp); -	rb = mmap(0, 202 * 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fp, 0); -	if (!rb) { -		printf("mmap failed\n"); -		exit; +	d.offset = 14; +	d.count = 1; +	d.buf[0] = (1<<8) | (1<<9); +	ioctl(fp, USRP_E_WRITE_CTL16, &d); + +	page_size = getpagesize(); + +	ret = ioctl(fp, USRP_E_GET_RB_INFO, &rb_size); + +	map_size = (rb_size.num_pages_rx_flags + rb_size.num_pages_tx_flags) * page_size + +		(rb_size.num_rx_frames + rb_size.num_tx_frames) * (page_size >> 1); + +	rb = mmap(0, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fp, 0); +	if (rb == MAP_FAILED) { +		perror("mmap failed"); +		return -1;  	} +	printf("rb = %p\n", rb); + +	rxi = rb; +	rx_buf = rb + (rb_size.num_pages_rx_flags * page_size); +	txi = rb +  (rb_size.num_pages_rx_flags * page_size) + +		(rb_size.num_rx_frames * page_size >> 1); +	tx_buf = rb +  (rb_size.num_pages_rx_flags * page_size) + +		(rb_size.num_rx_frames * page_size >> 1) + +		(rb_size.num_pages_tx_flags * page_size); + +	printf("rxi = %p, rx_buf = %p, txi = %p, tx_buf = %p\n", rxi, rx_buf, txi, tx_buf); + +	if ((ret = sched_setscheduler(0, SCHED_RR, &s))) +		perror("sched_setscheduler"); -	sched_setscheduler(0, SCHED_RR, &s);  	error = 0;  #if 1 @@ -228,4 +268,6 @@ int main(int argc, char *argv[])  		sleep(1000000000);  	printf("Done sleeping\n"); + +	return 0;  } diff --git a/host/apps/omap_debug/usrp-e-crc-rw.c b/host/usrp_e_utils/usrp-e-timed.c index f91c4fa85..06dfdf512 100644 --- a/host/apps/omap_debug/usrp-e-crc-rw.c +++ b/host/usrp_e_utils/usrp-e-timed.c @@ -10,7 +10,7 @@  #include <stddef.h>  #include <poll.h>  #include <sys/mman.h> -#include "usrp_e.h" +#include "linux/usrp_e.h"  // max length #define PKT_DATA_LENGTH 1016  static int packet_data_length; @@ -68,20 +68,21 @@ struct timeval delta_time(struct timeval f, struct timeval s)  static void *read_thread(void *threadid)  { -	int cnt; +	unsigned int cnt;  	int rx_pkt_cnt, rb_read; -	int i; +	unsigned int i;  	unsigned long crc, ck_sum;  	unsigned int rx_crc, pkt_len, pkt_seq;  	unsigned long bytes_transfered;  	struct timeval start_time;  	unsigned int prev_seq = 0;  	int first = 1; - +	long tid;  	__u8 *p; -	printf("Greetings from the reading thread!\n"); +	tid = (long)threadid; +	printf("Greetings from the reading thread(%ld)!\n", tid);  	// IMPORTANT: must assume max length packet from fpga @@ -97,7 +98,7 @@ static void *read_thread(void *threadid)  			struct pollfd pfd;  			pfd.fd = fp;  			pfd.events = POLLIN; -			ssize_t ret = poll(&pfd, 1, -1); +			poll(&pfd, 1, -1);  		}  		(*rxi)[rb_read].flags = RB_USER_PROCESS; @@ -136,7 +137,7 @@ static void *read_thread(void *threadid)  		}  		(*rxi)[rb_read].flags = RB_KERNEL; - +		write(fp, NULL, 1);  		if (rx_crc != ck_sum)  			printf("Ck_sum eror, calc ck_sum = %lX, rx ck_sum = %X\n", @@ -176,6 +177,7 @@ static void *read_thread(void *threadid)  			bytes_transfered = 0;  		}  	}	 +	return NULL;  }  static void *write_thread(void *threadid) @@ -185,9 +187,12 @@ static void *write_thread(void *threadid)  	unsigned long crc;  	unsigned long bytes_transfered;  	struct timeval start_time; +	unsigned int pkt_seq = 0; +	long tid;  	__u8 *p; -	printf("Greetings from the write thread!\n"); +	tid = (long)threadid; +	printf("Greetings from the write thread(%ld)!\n", tid);  	rb_write = 0;  	tx_pkt_cnt = 0; @@ -228,19 +233,27 @@ static void *write_thread(void *threadid)  			struct pollfd pfd;  			pfd.fd = fp;  			pfd.events = POLLOUT; -			ssize_t ret = poll(&pfd, 1, -1); +			poll(&pfd, 1, -1);  		}  //		printf("Got space\n"); +		for (i=8; i < tx_len-4; i++) { +			p[i] = i & 0xFF; +		} + +		*(unsigned int *) &p[0] = tx_len-4; +		*(unsigned int *) &p[4] = pkt_seq; + +		pkt_seq++; +  		crc = 0xFFFFFFFF;  		for (i = 0; i < tx_len-4; i++) { -			p[i] = i & 0xFF;  //			printf("%X ", p[i]);  			crc = ((crc >> 8) & 0x00FFFFFF) ^  				crc_tab[(crc ^ p[i]) & 0xFF];  		} -		*(int *) &p[tx_len-4] = crc; +		*(unsigned int *) &p[tx_len-4] = crc;  //		printf("\n crc = %lX\n", crc);  		(*txi)[rb_write].len = tx_len; @@ -273,13 +286,14 @@ static void *write_thread(void *threadid)  //		sleep(1);  	} +	return NULL;  }  int main(int argc, char *argv[])  {  	pthread_t tx, rx; -	long int t; +	long int t=0;  	int fpga_config_flag ,decimation;  	int ret, map_size, page_size;  	void *rb; @@ -315,7 +329,7 @@ int main(int argc, char *argv[])  		return -1;  	} -	printf("rb = %X\n", rb); +	printf("rb = %p\n", rb);  	rxi = rb;  	rx_buf = rb + (rb_size.num_pages_rx_flags * page_size); @@ -325,13 +339,13 @@ int main(int argc, char *argv[])  		(rb_size.num_rx_frames * page_size >> 1) +  		(rb_size.num_pages_tx_flags * page_size); -	fpga_config_flag = 0; +	fpga_config_flag = (1<<8);  	if (strcmp(argv[1], "w") == 0) -		fpga_config_flag |= (1 << 15); +		fpga_config_flag |= (1 << 11);  	else if (strcmp(argv[1], "r") == 0) -		fpga_config_flag |= (1 << 14); +		fpga_config_flag |= (1 << 10);  	else if (strcmp(argv[1], "rw") == 0) -		fpga_config_flag |= ((1 << 15) | (1 << 14)); +		fpga_config_flag |= ((1 << 10) | (1 << 11));  	fpga_config_flag |= decimation; @@ -344,7 +358,7 @@ int main(int argc, char *argv[])  	sched_setscheduler(0, SCHED_RR, &s); -	if (fpga_config_flag & (1 << 14)) { +	if (fpga_config_flag & (1 << 10)) {  		if (pthread_create(&rx, NULL, read_thread, (void *) t)) {  			printf("Failed to create rx thread\n");  			exit(-1); @@ -353,7 +367,7 @@ int main(int argc, char *argv[])  	sleep(1); -	if (fpga_config_flag & (1 << 15)) { +	if (fpga_config_flag & (1 << 11)) {  		if (pthread_create(&tx, NULL, write_thread, (void *) t)) {  			printf("Failed to create tx thread\n");  			exit(-1); 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) | 
