diff options
author | Josh Blum <josh@joshknows.com> | 2011-06-20 18:01:00 -0700 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2011-06-26 10:29:31 -0700 |
commit | 19b3b8245ba7e805c2328f6597fc24ad998b9b8b (patch) | |
tree | 47252d9730b13097fbcf7491f3e494d73ad05227 | |
parent | c96649d5c0e1b2dc17738b6904238eed66a3b9f0 (diff) | |
download | uhd-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.rst | 1 | ||||
-rw-r--r-- | host/lib/usrp/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/lib/usrp/b100/b100_impl.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/cores/CMakeLists.txt | 27 | ||||
-rw-r--r-- | host/lib/usrp/cores/i2c_core_100.cpp | 138 | ||||
-rw-r--r-- | host/lib/usrp/cores/i2c_core_100.hpp | 35 | ||||
-rw-r--r-- | host/lib/usrp/cores/spi_core_100.cpp | 88 | ||||
-rw-r--r-- | host/lib/usrp/cores/spi_core_100.hpp | 35 | ||||
-rw-r--r-- | host/lib/usrp/cores/wb_iface.hpp | 61 | ||||
-rw-r--r-- | host/lib/usrp/fx2/CMakeLists.txt | 2 |
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) |