diff options
author | michael-west <michael.west@ettus.com> | 2014-07-30 11:54:26 -0700 |
---|---|---|
committer | michael-west <michael.west@ettus.com> | 2014-07-30 11:54:26 -0700 |
commit | 35fc42f9fcbc5a791bdabc92086a51a2279563f1 (patch) | |
tree | fd053dd7e462fd49759ae255334de6d5c5aefd59 /host/lib/usrp/x300 | |
parent | bca5edb57979983a9eb8d6cd1016961552ad217c (diff) | |
parent | eafae66c030aa86e9da127de4f6d5ec4fd641c59 (diff) | |
download | uhd-35fc42f9fcbc5a791bdabc92086a51a2279563f1.tar.gz uhd-35fc42f9fcbc5a791bdabc92086a51a2279563f1.tar.bz2 uhd-35fc42f9fcbc5a791bdabc92086a51a2279563f1.zip |
Merge branch 'maint' into uhd/bug492
Conflicts:
host/lib/usrp/b200/b200_impl.cpp
Diffstat (limited to 'host/lib/usrp/x300')
-rw-r--r-- | host/lib/usrp/x300/x300_fw_uart.cpp | 93 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 31 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 10 |
3 files changed, 106 insertions, 28 deletions
diff --git a/host/lib/usrp/x300/x300_fw_uart.cpp b/host/lib/usrp/x300/x300_fw_uart.cpp index 943b2d9fa..b0fae124d 100644 --- a/host/lib/usrp/x300/x300_fw_uart.cpp +++ b/host/lib/usrp/x300/x300_fw_uart.cpp @@ -38,6 +38,8 @@ struct x300_uart_iface : uart_iface rxpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_ADDR)); txpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_ADDR)); poolsize = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32)); + _rxcache.resize(poolsize); + _last_device_rxoffset = rxoffset; //this->write_uart("HELLO UART\n"); //this->read_uart(0.1); } @@ -54,6 +56,7 @@ struct x300_uart_iface : uart_iface void write_uart(const std::string &buff) { + boost::mutex::scoped_lock(_write_mutex); BOOST_FOREACH(const char ch, buff) { if (ch == '\n') this->putchar('\r'); @@ -63,39 +66,99 @@ struct x300_uart_iface : uart_iface int getchar(void) { - if (_iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)) != rxoffset) + if (rxoffset == _last_device_rxoffset) + return -1; + + rxoffset++; + return static_cast<int>(_rxcache[(rxoffset/4) % poolsize] >> ((rxoffset%4)*8) & 0xFF); + } + + void update_cache(void) + { + boost::uint32_t device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); + boost::uint32_t delta = device_rxoffset - rxoffset; + + while (delta) { - const int shift = ((rxoffset%4) * 8); - const char ch = _iface->peek32(SR_ADDR(rxpool, rxoffset/4)) >> shift; - rxoffset = (rxoffset + 1) % (poolsize*4); - return ch; + if (delta >= poolsize*4) + { + // all the data is new - reload the entire cache + for (boost::uint32_t i = 0; i < poolsize; i++) + _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); + + // set rxoffset to the end of the first string + rxoffset = device_rxoffset - (poolsize*4) + 1; + while (static_cast<char>((_rxcache[(rxoffset/4) % poolsize] >> ((rxoffset%4)*8) & 0xFF)) != '\n') + ++rxoffset; + + // clear the partial string in the buffer; + _rxbuff.clear(); + } + else if (rxoffset == _last_device_rxoffset) + { + // new data was added - refresh the portion of the cache that was updated + for (boost::uint32_t i = ((_last_device_rxoffset+1)/4) % poolsize; i != (((device_rxoffset)/4)+1) % poolsize; i = (i+1) % poolsize) + { + _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); + } + } else { + // there is new data, but we aren't done with what we have - check back later + break; + } + + _last_device_rxoffset = device_rxoffset; + + // check again to see if anything changed while we were updating the cache + device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); + delta = device_rxoffset - rxoffset; } - return -1; } std::string read_uart(double timeout) { + boost::mutex::scoped_lock(_read_mutex); const boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6)); std::string buff; + while (true) { - const int ch = this->getchar(); - if (ch == -1) + // Update cache + this->update_cache(); + + // Get available characters + for (int ch = this->getchar(); ch != -1; ch = this->getchar()) { - if (boost::get_system_time() > exit_time) break; - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - continue; + // skip carriage returns + if (ch == '\r') + continue; + + // store character to buffer + _rxbuff += std::string(1, (char)ch); + + // newline found - return string + if (ch == '\n') + { + buff = _rxbuff; + _rxbuff.clear(); + return buff; + } } - if (ch == '\r') continue; - buff += std::string(1, (char)ch); - if (ch == '\n') break; + + // no more characters - check time + if (boost::get_system_time() > exit_time) + break; } - //UHD_VAR(buff); + return buff; } wb_iface::sptr _iface; boost::uint32_t rxoffset, txoffset, txword32, rxpool, txpool, poolsize; + boost::uint32_t _last_device_rxoffset; + std::vector<boost::uint32_t> _rxcache; + std::string _rxbuff; + boost::mutex _read_mutex; + boost::mutex _write_mutex; }; uart_iface::sptr x300_make_uart_iface(wb_iface::sptr iface) diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index fdf216cf2..3561bc2f1 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -841,8 +841,9 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) try { wait_for_ref_locked(mb.zpu_ctrl, 1.0); } catch (uhd::exception::runtime_error &e) { - UHD_MSG(warning) << "Clock reference failed to lock to internal source during device initialization. " << - "Check for the lock before operation or ignore this warning if using another clock source." << std::endl; + // Ignore for now - It can sometimes take longer than 1 second to lock and that is OK. + //UHD_MSG(warning) << "Clock reference failed to lock to internal source during device initialization. " << + // "Check for the lock before operation or ignore this warning if using another clock source." << std::endl; } _tree->access<std::string>(mb_path / "time_source" / "value").set("internal"); UHD_MSG(status) << "References initialized to internal sources" << std::endl; @@ -1079,9 +1080,13 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name) this->update_atr_leds(mb.radio_perifs[radio_index].leds, ""); //init anyway, even if never called //bind frontend corrections to the dboard freq props + const fs_path db_tx_fe_path = db_path / "tx_frontends"; + BOOST_FOREACH(const std::string &name, _tree->list(db_tx_fe_path)) { + _tree->access<double>(db_tx_fe_path / name / "freq" / "value") + .subscribe(boost::bind(&x300_impl::set_tx_fe_corrections, this, mb_path, slot_name, _1)); + } const fs_path db_rx_fe_path = db_path / "rx_frontends"; - BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) - { + BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) { _tree->access<double>(db_rx_fe_path / name / "freq" / "value") .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, slot_name, _1)); } @@ -1092,6 +1097,11 @@ void x300_impl::set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::st apply_rx_fe_corrections(this->get_tree()->subtree(mb_path), fe_name, lo_freq); } +void x300_impl::set_tx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq) +{ + apply_tx_fe_corrections(this->get_tree()->subtree(mb_path), fe_name, lo_freq); +} + boost::uint32_t get_pcie_dma_channel(boost::uint8_t destination, boost::uint8_t prefix) { static const boost::uint32_t RADIO_GRP_SIZE = 3; @@ -1108,8 +1118,7 @@ x300_impl::both_xports_t x300_impl::make_transport( const boost::uint8_t& destination, const boost::uint8_t& prefix, const uhd::device_addr_t& args, - boost::uint32_t& sid -) + boost::uint32_t& sid) { mboard_members_t &mb = _mb[mb_index]; both_xports_t xports; @@ -1131,12 +1140,12 @@ x300_impl::both_xports_t x300_impl::make_transport( if (mb.xport_path == "nirio") { default_buff_args.send_frame_size = (prefix == X300_RADIO_DEST_PREFIX_TX) - ? X300_PCIE_DATA_FRAME_SIZE + ? X300_PCIE_TX_DATA_FRAME_SIZE : X300_PCIE_MSG_FRAME_SIZE; default_buff_args.recv_frame_size = (prefix == X300_RADIO_DEST_PREFIX_RX) - ? X300_PCIE_DATA_FRAME_SIZE + ? X300_PCIE_RX_DATA_FRAME_SIZE : X300_PCIE_MSG_FRAME_SIZE; default_buff_args.num_send_frames = @@ -1206,10 +1215,10 @@ x300_impl::both_xports_t x300_impl::make_transport( << std::endl; } - size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; - size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; + size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; + size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; - // Make sure frame sizes do not exceed the max available value supported by UHD + // Make sure frame sizes do not exceed the max available value supported by UHD default_buff_args.send_frame_size = (prefix == X300_RADIO_DEST_PREFIX_TX) ? std::min(system_max_send_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE) diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 80f3e8faa..578e96383 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -63,7 +63,11 @@ static const size_t X300_RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib static const double X300_RX_SW_BUFF_FULL_FACTOR = 0.90; //Buffer should ideally be 90% full. static const size_t X300_RX_FC_REQUEST_FREQ = 32; //per flow-control window -static const size_t X300_PCIE_DATA_FRAME_SIZE = 8192; //bytes +//The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements deep for TX +//where an element is 8 bytes. For best throughput ensure that the data frame fits in these buffers. +//Also ensure that the kernel has enough frames to hold buffered TX and RX data +static const size_t X300_PCIE_RX_DATA_FRAME_SIZE = 8184; //bytes +static const size_t X300_PCIE_TX_DATA_FRAME_SIZE = 8192; //bytes static const size_t X300_PCIE_DATA_NUM_FRAMES = 2048; static const size_t X300_PCIE_MSG_FRAME_SIZE = 256; //bytes static const size_t X300_PCIE_MSG_NUM_FRAMES = 32; @@ -207,7 +211,7 @@ private: //perifs in each radio radio_perifs_t radio_perifs[2]; //!< This is hardcoded s.t. radio_perifs[0] points to slot A and [1] to B uhd::usrp::dboard_eeprom_t db_eeproms[8]; - //! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs + //! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs size_t get_radio_index(const std::string &slot_name) { UHD_ASSERT_THROW(slot_name == "A" or slot_name == "B"); return slot_name == "A" ? 0 : 1; @@ -317,6 +321,8 @@ private: uhd::dict<std::string, uhd::usrp::dboard_iface::sptr> _dboard_ifaces; void set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq); + void set_tx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq); + /*! Update the IQ MUX settings for the radio peripheral according to given subdev spec. * |