aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-06-20 18:01:00 -0700
committerJosh Blum <josh@joshknows.com>2011-06-26 10:29:31 -0700
commit19b3b8245ba7e805c2328f6597fc24ad998b9b8b (patch)
tree47252d9730b13097fbcf7491f3e494d73ad05227
parentc96649d5c0e1b2dc17738b6904238eed66a3b9f0 (diff)
downloaduhd-19b3b8245ba7e805c2328f6597fc24ad998b9b8b.tar.gz
uhd-19b3b8245ba7e805c2328f6597fc24ad998b9b8b.tar.bz2
uhd-19b3b8245ba7e805c2328f6597fc24ad998b9b8b.zip
usrp: created core controllers for i2c and spi on 100 series
-rw-r--r--host/docs/images.rst1
-rw-r--r--host/lib/usrp/CMakeLists.txt1
-rw-r--r--host/lib/usrp/b100/b100_impl.hpp2
-rw-r--r--host/lib/usrp/cores/CMakeLists.txt27
-rw-r--r--host/lib/usrp/cores/i2c_core_100.cpp138
-rw-r--r--host/lib/usrp/cores/i2c_core_100.hpp35
-rw-r--r--host/lib/usrp/cores/spi_core_100.cpp88
-rw-r--r--host/lib/usrp/cores/spi_core_100.hpp35
-rw-r--r--host/lib/usrp/cores/wb_iface.hpp61
-rw-r--r--host/lib/usrp/fx2/CMakeLists.txt2
10 files changed, 389 insertions, 1 deletions
diff --git a/host/docs/images.rst b/host/docs/images.rst
index adfa6d530..c0645a821 100644
--- a/host/docs/images.rst
+++ b/host/docs/images.rst
@@ -14,6 +14,7 @@ The methods of loading images into the device varies among devices:
* **USRP2:** The user must manually write the images onto the USRP2 SD card.
* **USRP-N Series:** The user must manually transfer the images over ethernet.
* **USRP-E Series:** The host code will automatically load the FPGA at runtime.
+* **USRP-B Series:** The host code will automatically load the FPGA at runtime.
------------------------------------------------------------------------
Pre-built images
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index 45498e3b4..0c964825c 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -33,6 +33,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/tune_helper.cpp
)
+INCLUDE_SUBDIRECTORY(cores)
INCLUDE_SUBDIRECTORY(dboard)
INCLUDE_SUBDIRECTORY(fx2)
INCLUDE_SUBDIRECTORY(usrp1)
diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp
index 2cea57eb5..b2381ef65 100644
--- a/host/lib/usrp/b100/b100_impl.hpp
+++ b/host/lib/usrp/b100/b100_impl.hpp
@@ -34,7 +34,7 @@
#ifndef INCLUDED_B100_IMPL_HPP
#define INCLUDED_B100_IMPL_HPP
-static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.bin";
+static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx";
static const std::string B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin";
static const boost::uint16_t B100_FW_COMPAT_NUM = 0x02;
static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x05;
diff --git a/host/lib/usrp/cores/CMakeLists.txt b/host/lib/usrp/cores/CMakeLists.txt
new file mode 100644
index 000000000..588726ad5
--- /dev/null
+++ b/host/lib/usrp/cores/CMakeLists.txt
@@ -0,0 +1,27 @@
+#
+# 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/>.
+#
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/i2c_core_100.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/spi_core_100.cpp
+)
diff --git a/host/lib/usrp/cores/i2c_core_100.cpp b/host/lib/usrp/cores/i2c_core_100.cpp
new file mode 100644
index 000000000..12352f108
--- /dev/null
+++ b/host/lib/usrp/cores/i2c_core_100.cpp
@@ -0,0 +1,138 @@
+//
+// 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/>.
+//
+
+#include "i2c_core_100.hpp"
+#include <uhd/exception.hpp>
+#include <uhd/utils/msg.hpp>
+#include <boost/thread/thread.hpp> //sleep
+
+#define REG_I2C_PRESCALER_LO _base + 0
+#define REG_I2C_PRESCALER_HI _base + 2
+#define REG_I2C_CTRL _base + 4
+#define REG_I2C_DATA _base + 6
+#define REG_I2C_CMD_STATUS _base + 8
+
+//
+// STA, STO, RD, WR, and IACK bits are cleared automatically
+//
+
+#define I2C_CTRL_EN (1 << 7) // core enable
+#define I2C_CTRL_IE (1 << 6) // interrupt enable
+
+#define I2C_CMD_START (1 << 7) // generate (repeated) start condition
+#define I2C_CMD_STOP (1 << 6) // generate stop condition
+#define I2C_CMD_RD (1 << 5) // read from slave
+#define I2C_CMD_WR (1 << 4) // write to slave
+#define I2C_CMD_NACK (1 << 3) // when a rcvr, send ACK (ACK=0) or NACK (ACK=1)
+#define I2C_CMD_RSVD_2 (1 << 2) // reserved
+#define I2C_CMD_RSVD_1 (1 << 1) // reserved
+#define I2C_CMD_IACK (1 << 0) // set to clear pending interrupt
+
+#define I2C_ST_RXACK (1 << 7) // Received acknowledgement from slave (1 = NAK, 0 = ACK)
+#define I2C_ST_BUSY (1 << 6) // 1 after START signal detected; 0 after STOP signal detected
+#define I2C_ST_AL (1 << 5) // Arbitration lost. 1 when core lost arbitration
+#define I2C_ST_RSVD_4 (1 << 4) // reserved
+#define I2C_ST_RSVD_3 (1 << 3) // reserved
+#define I2C_ST_RSVD_2 (1 << 2) // reserved
+#define I2C_ST_TIP (1 << 1) // Transfer-in-progress
+#define I2C_ST_IP (1 << 0) // Interrupt pending
+
+using namespace uhd;
+
+class i2c_core_100_impl : public i2c_core_100{
+public:
+ i2c_core_100_impl(wb_iface::sptr iface, const size_t base):
+ _iface(iface), _base(base)
+ {
+ //init I2C FPGA interface.
+ _iface->poke16(REG_I2C_CTRL, 0x0000);
+ //set prescalers to operate at 400kHz: WB_CLK is 64MHz...
+ static const boost::uint32_t i2c_datarate = 400000;
+ static const boost::uint32_t wishbone_clk = 64000000; //FIXME should go somewhere else
+ boost::uint16_t prescaler = wishbone_clk / (i2c_datarate*5) - 1;
+ _iface->poke16(REG_I2C_PRESCALER_LO, prescaler & 0xFF);
+ _iface->poke16(REG_I2C_PRESCALER_HI, (prescaler >> 8) & 0xFF);
+ _iface->poke16(REG_I2C_CTRL, I2C_CTRL_EN); //enable I2C core
+ }
+
+ void write_i2c(
+ boost::uint8_t addr,
+ const byte_vector_t &bytes
+ ){
+ _iface->poke16(REG_I2C_DATA, (addr << 1) | 0); //addr and read bit (0)
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_WR | I2C_CMD_START | (bytes.size() == 0 ? I2C_CMD_STOP : 0));
+
+ //wait for previous transfer to complete
+ if (not wait_chk_ack()) {
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_STOP);
+ return;
+ }
+
+ for (size_t i = 0; i < bytes.size(); i++) {
+ _iface->poke16(REG_I2C_DATA, bytes[i]);
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_WR | ((i == (bytes.size() - 1)) ? I2C_CMD_STOP : 0));
+ if(!wait_chk_ack()) {
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_STOP);
+ return;
+ }
+ }
+ }
+
+ byte_vector_t read_i2c(
+ boost::uint8_t addr,
+ size_t num_bytes
+ ){
+ byte_vector_t bytes;
+ if (num_bytes == 0) return bytes;
+
+ while (_iface->peek16(REG_I2C_CMD_STATUS) & I2C_ST_BUSY);
+
+ _iface->poke16(REG_I2C_DATA, (addr << 1) | 1); //addr and read bit (1)
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_WR | I2C_CMD_START);
+ //wait for previous transfer to complete
+ if (not wait_chk_ack()) {
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_STOP);
+ }
+ for (size_t i = 0; i < num_bytes; i++) {
+ _iface->poke16(REG_I2C_CMD_STATUS, I2C_CMD_RD | ((num_bytes == i+1) ? (I2C_CMD_STOP | I2C_CMD_NACK) : 0));
+ i2c_wait();
+ bytes.push_back(boost::uint8_t(_iface->peek16(REG_I2C_DATA)));
+ }
+ return bytes;
+ }
+
+private:
+ void i2c_wait(void) {
+ for (size_t i = 0; i < 100; i++){
+ if ((_iface->peek16(REG_I2C_CMD_STATUS) & I2C_ST_TIP) == 0) return;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1));
+ }
+ UHD_MSG(error) << "i2c_core_100: i2c_wait timeout" << std::endl;
+ }
+
+ bool wait_chk_ack(void){
+ i2c_wait();
+ return (_iface->peek16(REG_I2C_CMD_STATUS) & I2C_ST_RXACK) == 0;
+ }
+
+ wb_iface::sptr _iface;
+ const size_t _base;
+};
+
+i2c_core_100::sptr i2c_core_100::make(wb_iface::sptr iface, const size_t base){
+ return sptr(new i2c_core_100_impl(iface, base));
+}
diff --git a/host/lib/usrp/cores/i2c_core_100.hpp b/host/lib/usrp/cores/i2c_core_100.hpp
new file mode 100644
index 000000000..f14d14f2a
--- /dev/null
+++ b/host/lib/usrp/cores/i2c_core_100.hpp
@@ -0,0 +1,35 @@
+//
+// 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_USRP_I2C_CORE_100_HPP
+#define INCLUDED_LIBUHD_USRP_I2C_CORE_100_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/serial.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include "wb_iface.hpp"
+
+class i2c_core_100 : boost::noncopyable, public uhd::i2c_iface{
+public:
+ typedef boost::shared_ptr<i2c_core_100> sptr;
+
+ //! makes a new spi core from iface and slave base
+ sptr make(wb_iface::sptr iface, const size_t base);
+};
+
+#endif /* INCLUDED_LIBUHD_USRP_I2C_CORE_100_HPP */
diff --git a/host/lib/usrp/cores/spi_core_100.cpp b/host/lib/usrp/cores/spi_core_100.cpp
new file mode 100644
index 000000000..d11a499a9
--- /dev/null
+++ b/host/lib/usrp/cores/spi_core_100.cpp
@@ -0,0 +1,88 @@
+//
+// 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/>.
+//
+
+#include "spi_core_100.hpp"
+#include <uhd/exception.hpp>
+#include <uhd/utils/msg.hpp>
+#include <boost/thread/thread.hpp> //sleep
+
+#define REG_SPI_TXRX0 _base + 0
+#define REG_SPI_TXRX1 _base + 4
+#define REG_SPI_TXRX2 _base + 8
+#define REG_SPI_TXRX3 _base + 12
+#define REG_SPI_CTRL _base + 16
+#define REG_SPI_DIV _base + 20
+#define REG_SPI_SS _base + 24
+
+//spi ctrl register bit definitions
+#define SPI_CTRL_ASS (1<<13)
+#define SPI_CTRL_IE (1<<12)
+#define SPI_CTRL_LSB (1<<11)
+#define SPI_CTRL_TXNEG (1<<10) //mosi edge, push on falling edge when 1
+#define SPI_CTRL_RXNEG (1<< 9) //miso edge, latch on falling edge when 1
+#define SPI_CTRL_GO_BSY (1<< 8)
+#define SPI_CTRL_CHAR_LEN_MASK 0x7F
+
+using namespace uhd;
+
+class spi_core_100_impl : public spi_core_100{
+public:
+ spi_core_100_impl(wb_iface::sptr iface, const size_t base):
+ _iface(iface), _base(base) { /* NOP */}
+
+ boost::uint32_t transact_spi(
+ int which_slave,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits,
+ bool readback
+ ){
+ UHD_ASSERT_THROW(num_bits <= 32 and (num_bits % 8) == 0);
+
+ int edge_flags = ((config.miso_edge==spi_config_t::EDGE_FALL) ? SPI_CTRL_RXNEG : 0) |
+ ((config.mosi_edge==spi_config_t::EDGE_FALL) ? 0 : SPI_CTRL_TXNEG)
+ ;
+ boost::uint16_t ctrl = SPI_CTRL_ASS | (SPI_CTRL_CHAR_LEN_MASK & num_bits) | edge_flags;
+
+ spi_wait();
+ _iface->poke16(REG_SPI_DIV, 0x0001); // = fpga_clk / 4
+ _iface->poke32(REG_SPI_SS, which_slave & 0xFFFF);
+ _iface->poke32(REG_SPI_TXRX0, data);
+ _iface->poke16(REG_SPI_CTRL, ctrl);
+ _iface->poke16(REG_SPI_CTRL, ctrl | SPI_CTRL_GO_BSY);
+
+ if (not readback) return 0;
+ spi_wait();
+ return _iface->peek32(REG_SPI_TXRX0);
+ }
+
+private:
+ void spi_wait(void) {
+ for (size_t i = 0; i < 100; i++){
+ if ((_iface->peek16(REG_SPI_CTRL) & SPI_CTRL_GO_BSY) == 0) return;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1));
+ }
+ UHD_MSG(error) << "spi_core_100: spi_wait timeout" << std::endl;
+ }
+
+ wb_iface::sptr _iface;
+ const size_t _base;
+};
+
+spi_core_100::sptr spi_core_100::make(wb_iface::sptr iface, const size_t base){
+ return sptr(new spi_core_100_impl(iface, base));
+}
diff --git a/host/lib/usrp/cores/spi_core_100.hpp b/host/lib/usrp/cores/spi_core_100.hpp
new file mode 100644
index 000000000..2fd6b5206
--- /dev/null
+++ b/host/lib/usrp/cores/spi_core_100.hpp
@@ -0,0 +1,35 @@
+//
+// 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_USRP_SPI_CORE_100_HPP
+#define INCLUDED_LIBUHD_USRP_SPI_CORE_100_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/serial.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include "wb_iface.hpp"
+
+class spi_core_100 : boost::noncopyable, public uhd::spi_iface{
+public:
+ typedef boost::shared_ptr<spi_core_100> sptr;
+
+ //! makes a new spi core from iface and slave base
+ sptr make(wb_iface::sptr iface, const size_t base);
+};
+
+#endif /* INCLUDED_LIBUHD_USRP_SPI_CORE_100_HPP */
diff --git a/host/lib/usrp/cores/wb_iface.hpp b/host/lib/usrp/cores/wb_iface.hpp
new file mode 100644
index 000000000..8a873e5dc
--- /dev/null
+++ b/host/lib/usrp/cores/wb_iface.hpp
@@ -0,0 +1,61 @@
+//
+// 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_USRP_WB_IFACE_HPP
+#define INCLUDED_LIBUHD_USRP_WB_IFACE_HPP
+
+#include <uhd/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+class wb_iface : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<wb_iface> sptr;
+ typedef boost::uint32_t wb_addr_type;
+
+ /*!
+ * Write a register (32 bits)
+ * \param addr the address
+ * \param data the 32bit data
+ */
+ virtual void poke32(wb_addr_type addr, boost::uint32_t data) = 0;
+
+ /*!
+ * Read a register (32 bits)
+ * \param addr the address
+ * \return the 32bit data
+ */
+ virtual boost::uint32_t peek32(wb_addr_type addr) = 0;
+
+ /*!
+ * Write a register (16 bits)
+ * \param addr the address
+ * \param data the 16bit data
+ */
+ virtual void poke16(wb_addr_type addr, boost::uint16_t data) = 0;
+
+ /*!
+ * Read a register (16 bits)
+ * \param addr the address
+ * \return the 16bit data
+ */
+ virtual boost::uint16_t peek16(wb_addr_type addr) = 0;
+
+};
+
+#endif /* INCLUDED_LIBUHD_USRP_WB_IFACE_HPP */
diff --git a/host/lib/usrp/fx2/CMakeLists.txt b/host/lib/usrp/fx2/CMakeLists.txt
index 9d1e15e16..1bb5ad683 100644
--- a/host/lib/usrp/fx2/CMakeLists.txt
+++ b/host/lib/usrp/fx2/CMakeLists.txt
@@ -16,6 +16,8 @@
#
########################################################################
+# This file included, use CMake directory variables
+########################################################################
IF(ENABLE_USB)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../firmware/fx2/common)