aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/e100/e100_iface.cpp138
-rw-r--r--host/lib/usrp/e100/e100_impl.cpp10
2 files changed, 68 insertions, 80 deletions
diff --git a/host/lib/usrp/e100/e100_iface.cpp b/host/lib/usrp/e100/e100_iface.cpp
index d61ef42ad..e44e438b0 100644
--- a/host/lib/usrp/e100/e100_iface.cpp
+++ b/host/lib/usrp/e100/e100_iface.cpp
@@ -34,6 +34,57 @@ using namespace uhd;
using namespace uhd::usrp;
/***********************************************************************
+ * Sysfs GPIO wrapper class
+ **********************************************************************/
+class gpio{
+public:
+ gpio(const int num, const std::string &dir) : _num(num){
+ this->set_xport("export");
+ this->set_dir(dir);
+ _value_file.open(str(boost::format("/sys/class/gpio/gpio%d/value") % num).c_str(), std::ios_base::in | std::ios_base::out);
+ }
+ ~gpio(void){
+ _value_file.close();
+ this->set_dir("in");
+ this->set_xport("unexport");
+ }
+ void operator()(const int val){
+ _value_file << val << std::endl << std::flush;
+ }
+ int operator()(void){
+ std::string val;
+ std::getline(_value_file, val);
+ _value_file.seekg(0);
+ return int(val.at(0) - '0') & 0x1;
+ }
+private:
+ void set_xport(const std::string &xport){
+ std::ofstream export_file(("/sys/class/gpio/" + xport).c_str());
+ export_file << _num << std::endl << std::flush;
+ export_file.close();
+ }
+ void set_dir(const std::string &dir){
+ std::ofstream dir_file(str(boost::format("/sys/class/gpio/gpio%d/direction") % _num).c_str());
+ dir_file << dir << std::endl << std::flush;
+ dir_file.close();
+ }
+ const int _num;
+ std::fstream _value_file;
+};
+
+//We only init the gpios when we have to use them (in the aux spi call).
+//This way, the device discovery cannot unexport them from another process.
+struct iface_gpios_type{
+ typedef boost::shared_ptr<iface_gpios_type> sptr;
+ iface_gpios_type(void):
+ spi_sclk_gpio(65, "out"),
+ spi_sen_gpio(186, "out"),
+ spi_mosi_gpio(145, "out"),
+ spi_miso_gpio(147, "in"){}
+ gpio spi_sclk_gpio, spi_sen_gpio, spi_mosi_gpio, spi_miso_gpio;
+};
+
+/***********************************************************************
* I2C device node implementation wrapper
**********************************************************************/
class i2c_dev_iface : public i2c_iface{
@@ -281,92 +332,29 @@ public:
}
boost::uint32_t bitbang_spi(
- boost::uint32_t bits,
- size_t num_bits,
- bool readback
+ boost::uint32_t bits, size_t num_bits, bool readback
){
- boost::uint32_t rb_bits = 0;
+ if (_gpios.get() == NULL) { //init on demand...
+ _gpios = iface_gpios_type::sptr(new iface_gpios_type());
+ }
- _spi_bitbanger.spi_sen_gpio_write(0);
+ boost::uint32_t rb_bits = 0;
+ _gpios->spi_sen_gpio(0);
for (size_t i = 0; i < num_bits; i++){
- _spi_bitbanger.spi_sclk_gpio_write(0);
- _spi_bitbanger.spi_mosi_gpio_write((bits >> (num_bits-i-1)) & 0x1);
+ _gpios->spi_sclk_gpio(0);
+ _gpios->spi_mosi_gpio((bits >> (num_bits-i-1)) & 0x1);
boost::this_thread::sleep(boost::posix_time::microseconds(10));
- if (readback) rb_bits = (rb_bits << 1) | _spi_bitbanger.spi_miso_gpio_read();
- _spi_bitbanger.spi_sclk_gpio_write(1);
+ if (readback) rb_bits = (rb_bits << 1) | _gpios->spi_miso_gpio();
+ _gpios->spi_sclk_gpio(1);
boost::this_thread::sleep(boost::posix_time::microseconds(10));
}
- _spi_bitbanger.spi_sen_gpio_write(1);
+ _gpios->spi_sen_gpio(1);
boost::this_thread::sleep(boost::posix_time::microseconds(100));
-
return rb_bits;
}
- class bitbang_spi_guts{
- public:
- bitbang_spi_guts(void){
- //setup gpio pin directions
- this->set_gpio_direction(spi_sclk_gpio, "out");
- this->set_gpio_direction(spi_sen_gpio, "out");
- this->set_gpio_direction(spi_mosi_gpio, "out");
- this->set_gpio_direction(spi_miso_gpio, "in");
-
- //open the gpio pin values
- _spi_sclk_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_sclk_gpio).c_str());
- _spi_sen_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_sen_gpio).c_str());
- _spi_mosi_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_mosi_gpio).c_str());
- _spi_miso_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_miso_gpio).c_str());
- }
-
- ~bitbang_spi_guts(void){
- this->set_gpio_direction(spi_sclk_gpio, "in");
- this->set_gpio_direction(spi_sen_gpio, "in");
- this->set_gpio_direction(spi_mosi_gpio, "in");
- }
-
- void spi_sclk_gpio_write(int val){
- _spi_sclk_gpio_value << val << std::endl << std::flush;
- }
-
- void spi_sen_gpio_write(int val){
- _spi_sen_gpio_value << val << std::endl << std::flush;
- }
-
- void spi_mosi_gpio_write(int val){
- _spi_mosi_gpio_value << val << std::endl << std::flush;
- }
-
- int spi_miso_gpio_read(void){
- std::string val;
- std::getline(_spi_miso_gpio_value, val);
- _spi_miso_gpio_value.seekg(0);
- return int(val.at(0) - '0') & 0x1;
- }
-
- private:
- enum{
- spi_sclk_gpio = 65,
- spi_sen_gpio = 186,
- spi_mosi_gpio = 145,
- spi_miso_gpio = 147,
- };
-
- void set_gpio_direction(int gpio_num, const std::string &dir){
- std::ofstream export_file("/sys/class/gpio/export");
- export_file << gpio_num << std::endl << std::flush;
- export_file.close();
-
- std::ofstream dir_file(str(boost::format("/sys/class/gpio/gpio%d/direction") % gpio_num).c_str());
- dir_file << dir << std::endl << std::flush;
- dir_file.close();
- }
-
- std::ofstream _spi_sclk_gpio_value, _spi_sen_gpio_value, _spi_mosi_gpio_value;
- std::ifstream _spi_miso_gpio_value;
- };
-
/*******************************************************************
* UART
******************************************************************/
@@ -382,7 +370,7 @@ private:
int _node_fd;
i2c_dev_iface _i2c_dev_iface;
boost::mutex _ctrl_mutex;
- bitbang_spi_guts _spi_bitbanger;
+ iface_gpios_type::sptr _gpios;
};
/***********************************************************************
diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp
index 5485388f9..40ae20eaa 100644
--- a/host/lib/usrp/e100/e100_impl.cpp
+++ b/host/lib/usrp/e100/e100_impl.cpp
@@ -90,11 +90,6 @@ static device::sptr e100_make(const device_addr_t &device_addr){
//setup the main interface into fpga
const std::string node = device_addr["node"];
e100_iface::sptr iface = e100_iface::make();
- iface->open(node);
-
- //setup clock control here to ensure that the FPGA has a good clock before we continue
- const double master_clock_rate = device_addr.cast<double>("master_clock_rate", E100_DEFAULT_CLOCK_RATE);
- e100_clock_ctrl::sptr clock_ctrl = e100_clock_ctrl::make(iface, master_clock_rate);
//extract the fpga path for usrp-e and compute hash
const std::string e100_fpga_image = find_image_path(device_addr.get("fpga", E100_FPGA_FILE_NAME));
@@ -104,12 +99,17 @@ static device::sptr e100_make(const device_addr_t &device_addr){
// - close the device node
// - load the fpga bin file
// - re-open the device node
+ iface->open(node); //open here so we can do FPGA hash check
if (iface->peek32(E100_REG_RB_MISC_TEST32) != file_hash){
iface->close();
e100_load_fpga(e100_fpga_image);
iface->open(node);
}
+ //setup clock control here to ensure that the FPGA has a good clock before we continue
+ const double master_clock_rate = device_addr.cast<double>("master_clock_rate", E100_DEFAULT_CLOCK_RATE);
+ e100_clock_ctrl::sptr clock_ctrl = e100_clock_ctrl::make(iface, master_clock_rate);
+
//Perform wishbone readback tests, these tests also write the hash
bool test_fail = false;
UHD_MSG(status) << "Performing wishbone readback test... " << std::flush;