diff options
author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-04 11:04:07 -0800 |
---|---|---|
committer | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-04 11:04:07 -0800 |
commit | 178ac3f1c9950d383c8f64b3df464c0f943c4a23 (patch) | |
tree | 318ed621a7b59b7d34d4ce6e4a92f73f0bcef509 /host/include | |
parent | 2718ac110fa931cc29daf7cb3dc5ab6230ee02ab (diff) | |
download | uhd-178ac3f1c9950d383c8f64b3df464c0f943c4a23.tar.gz uhd-178ac3f1c9950d383c8f64b3df464c0f943c4a23.tar.bz2 uhd-178ac3f1c9950d383c8f64b3df464c0f943c4a23.zip |
Merging USRP X300 and X310 support!!
Diffstat (limited to 'host/include')
27 files changed, 2443 insertions, 8 deletions
diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index de39383c9..1090c243c 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -21,6 +21,7 @@ #include <uhd/config.hpp> #include <uhd/stream.hpp> #include <uhd/deprecated.hpp> +#include <uhd/property_tree.hpp> #include <uhd/types/device_addr.hpp> #include <boost/utility.hpp> #include <boost/shared_ptr.hpp> @@ -83,10 +84,12 @@ public: virtual tx_streamer::sptr get_tx_stream(const stream_args_t &args) = 0; //! Get access to the underlying property structure - virtual boost::shared_ptr<property_tree> get_tree(void) const = 0; + uhd::property_tree::sptr get_tree(void) const; #include <uhd/device_deprecated.ipp> +protected: + uhd::property_tree::sptr _tree; }; } //namespace uhd diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 1031da817..c22554e97 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2010-2011 Ettus Research LLC +# Copyright 2010-2013 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 @@ -23,6 +23,7 @@ UHD_INSTALL(FILES if_addrs.hpp udp_simple.hpp udp_zero_copy.hpp + tcp_zero_copy.hpp usb_control.hpp usb_zero_copy.hpp usb_device_handle.hpp diff --git a/host/include/uhd/transport/nirio/nifpga_lvbitx.h b/host/include/uhd/transport/nirio/nifpga_lvbitx.h new file mode 100644 index 000000000..598f7fcbe --- /dev/null +++ b/host/include/uhd/transport/nirio/nifpga_lvbitx.h @@ -0,0 +1,59 @@ +// +// Copyright 2013-2014 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_UHD_TRANSPORT_NIRIO_NIFPGA_LVBITX_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIFPGA_LVBITX_H + +#include <uhd/transport/nirio/nirio_resource_manager.h> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <boost/smart_ptr.hpp> + +namespace uhd { namespace niusrprio { + +class UHD_API nifpga_lvbitx { +public: + typedef boost::shared_ptr<nifpga_lvbitx> sptr; + + virtual ~nifpga_lvbitx() {}; + + virtual const char* get_bitfile_path() = 0; + virtual const char* get_signature() = 0; + virtual const char* get_bitstream_checksum() = 0; + + virtual size_t get_input_fifo_count() = 0; + virtual const char** get_input_fifo_names() = 0; + + virtual size_t get_output_fifo_count() = 0; + virtual const char** get_output_fifo_names() = 0; + + virtual size_t get_control_count() = 0; + virtual const char** get_control_names() = 0; + + virtual size_t get_indicator_count() = 0; + virtual const char** get_indicator_names() = 0; + + virtual void init_register_info(nirio_register_info_vtr& vtr) = 0; + virtual void init_fifo_info(nirio_fifo_info_vtr& vtr) = 0; + +protected: + std::string _get_bitstream_checksum(const std::string& file_path); + std::string _get_fpga_images_dir(const std::string search_paths); +}; +}} + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIFPGA_LVBITX_H */ + diff --git a/host/include/uhd/transport/nirio/nirio_driver_iface.h b/host/include/uhd/transport/nirio/nirio_driver_iface.h new file mode 100644 index 000000000..46a1146de --- /dev/null +++ b/host/include/uhd/transport/nirio/nirio_driver_iface.h @@ -0,0 +1,535 @@ +// +// Copyright 2013 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_UHD_TRANSPORT_NIRIO_NIRIO_DRIVER_IFACE_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_DRIVER_IFACE_H + +#include <stddef.h> +#include <stdint.h> +#include <string> +#include <uhd/transport/nirio/status.h> +#include <uhd/config.hpp> +#if defined(UHD_PLATFORM_WIN32) + #include <Windows.h> + #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union + #include <WinIoCtl.h> + #pragma warning(default:4201) +#elif defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) + #include <IOKit/IOKitLib.h> +#endif + +// CTL_CODE macro for non-win OSes +#ifndef UHD_PLATFORM_WIN32 + #define CTL_CODE(a,controlCode,b,c) (controlCode) +#endif + +namespace nirio_driver_iface { + +const uint32_t NIRIO_IOCTL_BASE = 0x800; + +const uint32_t NIRIO_IOCTL_SYNCOP = + CTL_CODE(FILE_DEVICE_UNKNOWN, + NIRIO_IOCTL_BASE + 4, + METHOD_OUT_DIRECT, + FILE_READ_DATA | FILE_WRITE_DATA); + ///< The synchronous operation code. Note: We + /// must use METHOD_OUT_DIRECT on the syncOp() + /// IOCTL to ensure the contents of the output + /// block are available in the kernel. + +const uint32_t NIRIO_IOCTL_GET_IFACE_NUM = + CTL_CODE(FILE_DEVICE_UNKNOWN, + NIRIO_IOCTL_BASE + 6, + METHOD_BUFFERED, + FILE_READ_DATA); ///< Get the interface number for a device + +const uint32_t NIRIO_IOCTL_GET_SESSION = + CTL_CODE(FILE_DEVICE_UNKNOWN, + NIRIO_IOCTL_BASE + 8, + METHOD_BUFFERED, + FILE_READ_ACCESS); ///< Gets a previously opened session to a device + +const uint32_t NIRIO_IOCTL_POST_OPEN = + CTL_CODE(FILE_DEVICE_UNKNOWN, + NIRIO_IOCTL_BASE + 9, + METHOD_BUFFERED, + FILE_READ_ACCESS); ///< Called after opening a session + +const uint32_t NIRIO_IOCTL_PRE_CLOSE = + CTL_CODE(FILE_DEVICE_UNKNOWN, + NIRIO_IOCTL_BASE + 10, + METHOD_BUFFERED, + FILE_READ_ACCESS); ///< Called before closing a session + + +// ------------------------------- +// Function Codes: defined as integers rather than enums because they +// are going to be carried accross boundaries so size matters + +namespace NIRIO_FUNC +{ + const uint32_t GET32 = 0x00000001; + const uint32_t SET32 = 0x00000002; + const uint32_t SET_DRIVER_CONFIG = 0x00000007; + const uint32_t FIFO = 0x00000008; + const uint32_t IO = 0x0000000A; + const uint32_t FIFO_STOP_ALL = 0x0000000C; + const uint32_t ADD_RESOURCE = 0x0000000D; + const uint32_t GET_STRING = 0x0000000E; + const uint32_t SET_STRING = 0x0000000F; + const uint32_t DOWNLOAD = 0x00000013; + const uint32_t RESET = 0x00000014; +} + +namespace NIRIO_RESOURCE +{ + const uint32_t INPUT_FIFO = 0xD0000001; + const uint32_t OUTPUT_FIFO = 0xD0000002; +} + +namespace NIRIO_FIFO +{ + const uint32_t CONFIGURE = 0x80000001; + const uint32_t START = 0x80000002; + const uint32_t STOP = 0x80000003; + const uint32_t READ = 0x80000004; + const uint32_t WRITE = 0x80000005; + const uint32_t WAIT = 0x80000006; + const uint32_t GRANT = 0x80000007; +} + +namespace NIRIO_IO +{ + const uint32_t POKE64 = 0xA0000005; + const uint32_t POKE32 = 0xA0000006; + const uint32_t POKE16 = 0xA0000007; + const uint32_t POKE8 = 0xA0000008; + const uint32_t PEEK64 = 0xA0000009; + const uint32_t PEEK32 = 0xA000000A; + const uint32_t PEEK16 = 0xA000000B; + const uint32_t PEEK8 = 0xA000000C; + const uint32_t READ_BLOCK = 0xA000000D; + const uint32_t WRITE_BLOCK = 0xA000000E; + const uint32_t GET_IO_WINDOW = 0xA000000F; + const uint32_t GET_IO_WINDOW_SIZE = 0xA0000010; +} + +struct nirio_ioctl_packet_t { + nirio_ioctl_packet_t( + void* const _outBuf, + const uint32_t _outSize, + const int32_t _statusCode) + { + outBuf._64BitField = 0; + outBuf.pointer = _outBuf; + outSize = _outSize; + statusCode = _statusCode; + }; + + union { + void* pointer; + uint64_t _64BitField; + } outBuf; + + uint32_t outSize; + int32_t statusCode; +}; + +struct nirio_ioctl_block_t +{ + uint64_t inBuf; + uint64_t outBuf; + uint32_t inBufLength; + uint32_t outBufLength; + uint32_t bytesReturned; + uint32_t padding; +}; + +struct nirio_syncop_in_params_t +{ + uint32_t function; + uint32_t subfunction; + + union + { + struct + { + uint32_t attribute; + uint32_t value; + } attribute32; + + struct + { + uint32_t attribute; + uint64_t value; + } attribute64; + + struct + { + uint32_t attribute; + } attributeStr; + + struct + { + uint32_t attribute; + } download; + + union + { + struct + { + uint32_t reserved_field_0_0_0; + } reserved_field_0_0; + struct + { + uint32_t reserved_field_0_1_0; + uint32_t reserved_field_0_1_1; + } reserved_field_0_1; + struct + { + uint32_t reserved_field_0_2_0; + } reserved_field_0_2; + } reserved_field_0; + + union + { + struct + { + uint32_t channel; + uint32_t baseAddress; + uint32_t depthInSamples; + uint32_t version; + } fifo; + struct + { + uint32_t channel; + uint32_t baseAddress; + uint32_t depthInSamples; + uint32_t version; + uint32_t scalarType; + uint32_t bitWidth; + } fifoWithDataType; + struct + { + uint64_t rangeBaseAddress; + uint32_t rangeSizeInBytes; + uint32_t rangeAttribute; + } atomic; // obsolete + } add; + + struct + { + uint32_t channel; + + union + { + struct + { + uint32_t requestedDepth; + uint8_t requiresActuals; + } config; + struct + { + uint32_t timeout; + } read; + struct + { + uint32_t timeout; + uint32_t scalarType; + uint32_t bitWidth; + } readWithDataType; + struct + { + uint32_t timeout; + } write; + struct + { + uint32_t timeout; + uint32_t scalarType; + uint32_t bitWidth; + } writeWithDataType; + struct + { + uint32_t elementsRequested; + uint32_t scalarType; + uint32_t bitWidth; + uint32_t timeout; + uint8_t output; + } wait; + struct + { + uint32_t elements; + } grant; + } op; + } fifo; + + struct + { + uint64_t reserved_field_1_0; + uint32_t reserved_field_1_1; + uint32_t reserved_field_1_2; + } reserved_field_1; // Obsolete + + struct + { + uint32_t offset; + union + { + uint64_t value64; + uint32_t value32; + uint16_t value16; + uint8_t value8; + } value; + union + { + uint32_t sizeToMap; + } memoryMappedIoWindow; + } io; + + struct + { + uint32_t reserved_field_2_0; + uint32_t reserved_field_2_1; + } reserved_field_2; + + struct + { + uint32_t reserved_field_3_0; + } reserved_field_3; + + union + { + struct + { + uint32_t reserved_field_4_0; + int32_t reserved_field_4_1; + } wait; + } reserved_field_4; + + } params; + + uint32_t inbufByteLen; + + union + { + const void* pointer; + uint64_t _64BitField; + } inbuf; +}; + +static inline void init_syncop_in_params(nirio_syncop_in_params_t& param, const void* const buf, const uint32_t len) +{ + param.inbuf._64BitField = 0; + param.inbuf.pointer = buf; + param.inbufByteLen = len; +} + + +struct nirio_syncop_out_params_t +{ + union + { + struct + { + uint32_t value; + } attribute32; + + struct + { + uint64_t value; + } attribute64; + + union + { + struct + { + uint32_t reserved_field_0_0; + } enable; + } reserved_field_0; + + struct + { + union + { + struct + { + uint32_t actualDepth; + uint32_t actualSize; + } config; + struct + { + uint32_t numberRead; + uint32_t numberRemaining; + } read; + struct + { + uint32_t numberRemaining; + } write; + struct + { + union + { + void* pointer; + uint64_t _64BitField; + } elements; + } wait; + } op; + } fifo; + + struct + { + union + { + union + { + uint64_t value64; + uint32_t value32; + uint16_t value16; + uint8_t value8; + } value; + union + { + void* memoryMappedAddress; + uint64_t _64BitField; + } memoryMappedIoWindow; + union + { + uint32_t size; + } memoryMappedIoWindowSize; + }; + } io; + + uint32_t stringLength; + + struct + { + uint32_t reserved_field_1_0; + } reserved_field_1; + + } params; + + uint32_t outbufByteLen; + + union + { + void* pointer; + uint64_t _64BitField; + } outbuf; +}; + +static inline void init_syncop_out_params(nirio_syncop_out_params_t& param, void* buf, uint32_t len) +{ + param.outbuf._64BitField = 0; + param.outbuf.pointer = buf; + param.outbufByteLen = len; +} + + + +//Device handle definition +#if defined(UHD_PLATFORM_LINUX) + typedef int rio_dev_handle_t; +#elif defined(UHD_PLATFORM_WIN32) + typedef HANDLE rio_dev_handle_t; +#elif defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) + typedef io_connect_t rio_dev_handle_t; +#else + #error OS not supported by nirio_driver_iface. +#endif +static const rio_dev_handle_t INVALID_RIO_HANDLE = ((rio_dev_handle_t)-1); + +//Memory mapping container definition +#if defined(UHD_PLATFORM_LINUX) + struct rio_mmap_t { + rio_mmap_t() : addr(NULL), size(0) {} + void *addr; + size_t size; + + bool is_null() { return (size == 0 || addr == NULL); } + }; +#elif defined(UHD_PLATFORM_WIN32) + enum access_mode_t { + ACCESS_MODE_READ, + ACCESS_MODE_WRITE + }; + + struct rio_mmap_params_t + { + uint64_t mapped_va_ptr; + uint64_t map_ready_event_handle; + uint32_t size; + uint16_t memoryType; + uint8_t access_mode; + }; + + struct rio_mmap_threadargs_t + { + rio_dev_handle_t device_handle; + rio_mmap_params_t params; + nirio_status status; + }; + + struct rio_mmap_t + { + rio_mmap_t() : addr(NULL) {} + void *addr; + HANDLE map_thread_handle; + rio_mmap_threadargs_t map_thread_args; + + bool is_null() { return addr == NULL; } + }; +#elif defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) + struct rio_mmap_t { + rio_mmap_t() : addr(NULL) {} + void *addr; + + bool is_null() { return addr == NULL; } + }; +#else + #error OS not supported by nirio_driver_iface. +#endif + + nirio_status rio_open( + const std::string& device_path, + rio_dev_handle_t& device_handle); + + void rio_close( + rio_dev_handle_t& device_handle); + + bool rio_isopen( + rio_dev_handle_t device_handle); + + nirio_status rio_ioctl( + rio_dev_handle_t device_handle, + uint32_t ioctl_code, + const void *write_buf, + size_t write_buf_len, + void *read_buf, + size_t read_buf_len); + + nirio_status rio_mmap( + rio_dev_handle_t device_handle, + uint16_t memory_type, + size_t size, + bool writable, + rio_mmap_t &map); + + nirio_status rio_munmap( + rio_mmap_t &map); +} + +#endif diff --git a/host/include/uhd/transport/nirio/nirio_err_template.h b/host/include/uhd/transport/nirio/nirio_err_template.h new file mode 100644 index 000000000..9235c0384 --- /dev/null +++ b/host/include/uhd/transport/nirio/nirio_err_template.h @@ -0,0 +1,66 @@ +// +// Copyright 2013-2014 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/>. +// + +/* + * NIRIO_ERR_INFO is undefined on purpose. + * This header is designed to be included with a custom definition of NIRIO_ERR_INFO + * To "generate" code in multiple files. This prevents duplication of code. + */ + +NIRIO_ERR_INFO(NiRio_Status_Success, 0, "No errors or warnings.") +NIRIO_ERR_INFO(NiRio_Status_FifoTimeout, -50400, "The timeout expired before the FIFO operation could complete.") +NIRIO_ERR_INFO(NiRio_Status_MemoryFull, -52000, "A memory allocation failed. Try again after rebooting.") +NIRIO_ERR_INFO(NiRio_Status_SoftwareFault, -52003, "An unexpected software error occurred.") +NIRIO_ERR_INFO(NiRio_Status_InvalidParameter, -52005, "A parameter to a function was not valid. This could be a NULL pointer, a bad value, etc.") +NIRIO_ERR_INFO(NiRio_Status_ResourceNotFound, -52006, "A required resource was not found. The NiFpga.* library, the RIO resource, or some other resource may be missing.") +NIRIO_ERR_INFO(NiRio_Status_ResourceNotInitialized, -52010, "A required resource was not properly initialized. This could occur if NiFpga_Initialize was not called or a required NiFpga_IrqContext was not reserved.") +NIRIO_ERR_INFO(NiRio_Status_FpgaAlreadyRunning, -61003, "The FPGA is already running.") +NIRIO_ERR_INFO(NiRio_Status_DeviceTypeMismatch, -61024, "The bitfile was not compiled for the specified resource's device type.") +NIRIO_ERR_INFO(NiRio_Status_CommunicationTimeout, -61046, "An error was detected in the communication between the host computer and the USRP device. This could be due to a hardware failure on the bus.") +NIRIO_ERR_INFO(NiRio_Status_IrqTimeout, -61060, "The timeout expired before any of the IRQs were asserted.") +NIRIO_ERR_INFO(NiRio_Status_CorruptBitfile, -61070, "The LVBITX configuration bitstream seems to be corrupt.") +NIRIO_ERR_INFO(NiRio_Status_BadDepth, -61072, "The requested FIFO depth is invalid. It is either 0 or an amount not supported by the hardware.") +NIRIO_ERR_INFO(NiRio_Status_BadReadWriteCount, -61073, "The number of FIFO elements is invalid. Either the number is greater than the depth of the host memory DMA FIFO, or more elements were requested for release than had been acquired.") +NIRIO_ERR_INFO(NiRio_Status_ClockLostLock, -61083, "A hardware clocking error occurred.") +NIRIO_ERR_INFO(NiRio_Status_FpgaBusy, -61141, "The operation could not be performed because the FPGA is busy.") +NIRIO_ERR_INFO(NiRio_Status_FpgaBusyFpgaInterfaceCApi, -61200, "The operation could not be performed because the FPGA is busy.") +NIRIO_ERR_INFO(NiRio_Status_FpgaBusyScanInterface, -61201, "The operation could not be performed because the chassis is in Scan Interface programming mode.") +NIRIO_ERR_INFO(NiRio_Status_FpgaBusyFpgaInterface, -61202, "The operation could not be performed because the FPGA is busy operating in FPGA Interface mode. Stop all activities on the FPGA before requesting this operation.") +NIRIO_ERR_INFO(NiRio_Status_FpgaBusyInteractive, -61203, "The operation could not be performed because the FPGA is busy operating in FPGA Interactive mode. Stop all activities on the FPGA before requesting this operation.") +NIRIO_ERR_INFO(NiRio_Status_FpgaBusyEmulation, -61204, "The operation could not be performed because the FPGA is busy operating in FPGA Emulation mode. Stop all activities on the FPGA before requesting this operation.") +NIRIO_ERR_INFO(NiRio_Status_GatedClockHandshakingViolation, -61216, "A gated clock has violated the handshaking protocol.") +NIRIO_ERR_INFO(NiRio_Status_RegionsOutstandingForSession, -61217, "A session cannot be closed, reset, nor can a bitfile be downloaded while DMA FIFO region references are still outstanding for the specified session.") +NIRIO_ERR_INFO(NiRio_Status_ElementsNotPermissibleToBeAcquired, -61219, "There are currently fewer unacquired elements left in the FIFO than are being requested. Release some acquired elements before acquiring more elements.") +NIRIO_ERR_INFO(NiRio_Status_InternalError, -61499, "An unexpected internal error occurred.") +NIRIO_ERR_INFO(NiRio_Status_AccessDenied, -63033, "Access to the local or remote system was denied.") +NIRIO_ERR_INFO(NiRio_Status_RpcConnectionError, -63040, "A connection could not be established to the specified remote device manager. Ensure that the devices are on, that NI-USRPRIO software is installed, and that the USRPRIO server is running and properly configured.") +NIRIO_ERR_INFO(NiRio_Status_RpcOperationError, -63042, "A fault on the network caused the RPC operation to fail.") +NIRIO_ERR_INFO(NiRio_Status_RpcSessionError, -63043, "The RPC session to the remote device manager is invalid. Ensure that the device is connected and try restarting the server.") +NIRIO_ERR_INFO(NiRio_Status_FifoReserved, -63082, "The operation could not complete because another session is accessing the FIFO. Close the other session and retry.") +NIRIO_ERR_INFO(NiRio_Status_FifoElementsCurrentlyAcquired, -63083, "A Configure FIFO, Stop FIFO, Read FIFO, or Write FIFO function was called while the host had acquired elements of the FIFO. Release all acquired elements before configuring, stopping, reading, or writing.") +NIRIO_ERR_INFO(NiRio_Status_MisalignedAccess, -63084, "A function was called using a misaligned address. The address must be a multiple of the size of the datatype.") +NIRIO_ERR_INFO(NiRio_Status_BitfileReadError, -63101, "A valid .lvbitx bitfile is required. If you are using a valid .lvbitx bitfile, the bitfile may not be compatible with the software you are using.") +NIRIO_ERR_INFO(NiRio_Status_SignatureMismatch, -63106, "The specified signature does not match the signature of the bitfile. If the bitfile has been recompiled, regenerate the C API and rebuild the application.") +NIRIO_ERR_INFO(NiRio_Status_IncompatibleBitfile, -63107, "The bitfile you are trying to use is not compatible with the version of NI-RIO installed on the target and/or the host.") +NIRIO_ERR_INFO(NiRio_Status_InvalidResourceName, -63192, "Either the supplied resource name is invalid as a RIO resource name, or the device was not found.") +NIRIO_ERR_INFO(NiRio_Status_FeatureNotSupported, -63193, "The requested feature is not supported.") +NIRIO_ERR_INFO(NiRio_Status_VersionMismatch, -63194, "Software version mismatch.") +NIRIO_ERR_INFO(NiRio_Status_InvalidSession, -63195, "The session is invalid or has been closed.") +NIRIO_ERR_INFO(NiRio_Status_OutOfHandles, -63198, "The maximum number of open FPGA sessions has been reached. Close some open sessions.") +NIRIO_ERR_INFO(NiRio_Status_DeviceLocked, -63031, "The operation is not allowed because another session in a different process is accessing the device. Close all other sessions and retry.") + + diff --git a/host/include/uhd/transport/nirio/nirio_fifo.h b/host/include/uhd/transport/nirio/nirio_fifo.h new file mode 100644 index 000000000..f7abb396f --- /dev/null +++ b/host/include/uhd/transport/nirio/nirio_fifo.h @@ -0,0 +1,132 @@ +// +// Copyright 2013-2014 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_UHD_TRANSPORT_NIRIO_NIRIO_FIFO_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_FIFO_H + +#include <uhd/transport/nirio/nirio_driver_iface.h> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <uhd/transport/nirio/status.h> +#include <boost/noncopyable.hpp> +#include <boost/smart_ptr.hpp> +#include <string> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> + +namespace uhd { namespace niusrprio { + +enum fifo_direction_t { + INPUT_FIFO, + OUTPUT_FIFO +}; + +enum nirio_scalar_t { + SCALAR_I8 = 1UL, + SCALAR_I16 = 2UL, + SCALAR_I32 = 3UL, + SCALAR_I64 = 4UL, + SCALAR_U8 = 5UL, + SCALAR_U16 = 6UL, + SCALAR_U32 = 7UL, + SCALAR_U64 = 8UL +}; + +struct datatype_info_t { + datatype_info_t(nirio_scalar_t t, uint32_t w):scalar_type(t),width(w) {} + nirio_scalar_t scalar_type; + uint32_t width; +}; + +template <typename data_t> +class nirio_fifo : private boost::noncopyable +{ +public: + typedef boost::shared_ptr< nirio_fifo<data_t> > sptr; + + nirio_fifo( + niriok_proxy& riok_proxy, + fifo_direction_t direction, + const std::string& name, + uint32_t fifo_instance); + virtual ~nirio_fifo(); + + nirio_status initialize( + const size_t requested_depth, + size_t& actual_depth, + size_t& actual_size); + + void finalize(); + + inline const std::string& get_name() const { return _name; } + inline uint32_t get_channel() const { return _fifo_channel; } + inline uint32_t get_direction() const { return _fifo_direction; } + inline uint32_t get_scalar_type() const { return _datatype_info.scalar_type; } + + nirio_status start(); + + nirio_status stop(); + + nirio_status acquire( + data_t*& elements, + const size_t elements_requested, + const uint32_t timeout, + size_t& elements_acquired, + size_t& elements_remaining); + + nirio_status release(const size_t elements); + + nirio_status read( + data_t* buf, + const uint32_t num_elements, + uint32_t timeout, + uint32_t& num_read, + uint32_t& num_remaining); + + nirio_status write( + const data_t* buf, + const uint32_t num_elements, + uint32_t timeout, + uint32_t& num_remaining); + +private: //Methods + bool _is_initialized(); + datatype_info_t _get_datatype_info(); + nirio_status _get_transfer_count(uint64_t& transfer_count); + nirio_status _ensure_transfer_completed(uint32_t timeout_ms); + +private: //Members + std::string _name; + fifo_direction_t _fifo_direction; + uint32_t _fifo_channel; + datatype_info_t _datatype_info; + size_t _acquired_pending; + nirio_driver_iface::rio_mmap_t _mem_map; + boost::recursive_mutex _mutex; + niriok_proxy* _riok_proxy_ptr; + + uint64_t _expected_xfer_count; + uint32_t _dma_base_addr; + + static const uint32_t FIFO_LOCK_TIMEOUT_IN_MS = 5000; +}; + +#include "nirio_fifo.ipp" + +}} + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_FIFO_H */ diff --git a/host/include/uhd/transport/nirio/nirio_fifo.ipp b/host/include/uhd/transport/nirio/nirio_fifo.ipp new file mode 100644 index 000000000..80a0c2a89 --- /dev/null +++ b/host/include/uhd/transport/nirio/nirio_fifo.ipp @@ -0,0 +1,378 @@ +// +// Copyright 2013-2014 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/>. +// + +#ifdef __clang__ + #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" +#elif defined(__GNUC__) + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +template <typename data_t> +nirio_fifo<data_t>::nirio_fifo( + niriok_proxy& riok_proxy, + fifo_direction_t direction, + const std::string& name, + uint32_t fifo_instance) : + _name(name), + _fifo_direction(direction), + _fifo_channel(fifo_instance), + _datatype_info(_get_datatype_info()), + _acquired_pending(0), + _mem_map(), + _riok_proxy_ptr(&riok_proxy), + _expected_xfer_count(0), + _dma_base_addr(0) +{ + nirio_status status = 0; + nirio_status_chain(_riok_proxy_ptr->set_attribute(ADDRESS_SPACE, BUS_INTERFACE), status); + uint32_t base_addr, addr_space_word; + nirio_status_chain(_riok_proxy_ptr->peek(0x1C, base_addr), status); + nirio_status_chain(_riok_proxy_ptr->peek(0xC, addr_space_word), status); + _dma_base_addr = base_addr + (_fifo_channel * (1<<((addr_space_word>>16)&0xF))); +} + +template <typename data_t> +nirio_fifo<data_t>::~nirio_fifo() +{ + finalize(); +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::initialize( + const size_t requested_depth, + size_t& actual_depth, + size_t& actual_size) +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized; + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + //Forcefully stop the fifo if it is running + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::STOP; + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::CONFIGURE; + + in.params.fifo.channel = _fifo_channel; + in.params.fifo.op.config.requestedDepth = static_cast<uint32_t>(requested_depth); + in.params.fifo.op.config.requiresActuals = 1; + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + if (nirio_status_fatal(status)) return status; + + actual_depth = out.params.fifo.op.config.actualDepth; + actual_size = out.params.fifo.op.config.actualSize; + + status = _riok_proxy_ptr->map_fifo_memory(_fifo_channel, actual_size, _mem_map); + return status; +} + +template <typename data_t> +void nirio_fifo<data_t>::finalize() +{ + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + if (!_mem_map.is_null()) { + stop(); + _riok_proxy_ptr->unmap_fifo_memory(_mem_map); + } +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::start() +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized; + + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::START; + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + if (nirio_status_not_fatal(status)) { + _acquired_pending = 0; + _expected_xfer_count = 0; + } + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::stop() +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized; + + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + if (_acquired_pending > 0) release(_acquired_pending); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::STOP; + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::acquire( + data_t*& elements, + const size_t elements_requested, + const uint32_t timeout, + size_t& elements_acquired, + size_t& elements_remaining) +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr || _mem_map.is_null()) return NiRio_Status_ResourceNotInitialized; + + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + uint32_t stuffed[2]; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + init_syncop_out_params(out, stuffed, sizeof(stuffed)); + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::WAIT; + + in.params.fifo.channel = _fifo_channel; + in.params.fifo.op.wait.elementsRequested = static_cast<uint32_t>(elements_requested); + in.params.fifo.op.wait.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); + in.params.fifo.op.wait.bitWidth = _datatype_info.width * 8; + in.params.fifo.op.wait.output = _fifo_direction == OUTPUT_FIFO; + in.params.fifo.op.wait.timeout = timeout; + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + + if (nirio_status_not_fatal(status)) { + elements = static_cast<data_t*>(out.params.fifo.op.wait.elements.pointer); + elements_acquired = stuffed[0]; + elements_remaining = stuffed[1]; + _acquired_pending = elements_acquired; + + if (UHD_NIRIO_RX_FIFO_XFER_CHECK_EN && + _riok_proxy_ptr->get_rio_quirks().rx_fifo_xfer_check_en() && + get_direction() == INPUT_FIFO + ) { + _expected_xfer_count += static_cast<uint64_t>(elements_requested * sizeof(data_t)); + status = _ensure_transfer_completed(timeout); + } + } + + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::release(const size_t elements) +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized; + + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::GRANT; + + in.params.fifo.channel = _fifo_channel; + in.params.fifo.op.grant.elements = static_cast<uint32_t>(elements); + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + _acquired_pending = 0; + + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::read( + data_t* buf, + const uint32_t num_elements, + uint32_t timeout, + uint32_t& num_read, + uint32_t& num_remaining) +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized; + + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + init_syncop_out_params(out, buf, num_elements * _datatype_info.width); + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::READ; + + in.params.fifo.channel = _fifo_channel; + in.params.fifo.op.readWithDataType.timeout = timeout; + in.params.fifo.op.readWithDataType.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); + in.params.fifo.op.readWithDataType.bitWidth = _datatype_info.width * 8; + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + + if (nirio_status_not_fatal(status) || status == NiRio_Status_FifoTimeout) { + num_read = out.params.fifo.op.read.numberRead; + num_remaining = out.params.fifo.op.read.numberRemaining; + } + + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::write( + const data_t* buf, + const uint32_t num_elements, + uint32_t timeout, + uint32_t& num_remaining) +{ + nirio_status status = NiRio_Status_Success; + if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized; + + boost::unique_lock<boost::recursive_mutex> lock(_mutex); + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + init_syncop_in_params(in, buf, num_elements * _datatype_info.width); + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; + in.subfunction = nirio_driver_iface::NIRIO_FIFO::WRITE; + + in.params.fifo.channel = _fifo_channel; + in.params.fifo.op.writeWithDataType.timeout = timeout; + in.params.fifo.op.readWithDataType.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); + in.params.fifo.op.readWithDataType.bitWidth = _datatype_info.width * 8; + + status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + + if (nirio_status_not_fatal(status) || status == NiRio_Status_FifoTimeout) { + num_remaining = out.params.fifo.op.write.numberRemaining; + } + + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::_get_transfer_count(uint64_t& transfer_count) +{ + //_riok_proxy_ptr must be valid and _mutex must be locked + + nirio_status status = NiRio_Status_Success; + uint32_t lower_half = 0, upper_half = 0; + nirio_status_chain(_riok_proxy_ptr->peek(_dma_base_addr + 0xA8, lower_half), status); //Latches both halves + nirio_status_chain(_riok_proxy_ptr->peek(_dma_base_addr + 0xAC, upper_half), status); + + if (nirio_status_not_fatal(status)) { + transfer_count = lower_half | (((uint64_t)upper_half) << 32); + } + return status; +} + +template <typename data_t> +nirio_status nirio_fifo<data_t>::_ensure_transfer_completed(uint32_t timeout_ms) +{ + //_riok_proxy_ptr must be valid and _mutex must be locked + + static const size_t MIN_TIMEOUT_IN_US = 2000; + + nirio_status status = NiRio_Status_Success; + uint64_t actual_xfer_count = 0; + nirio_status_chain(_get_transfer_count(actual_xfer_count), status); + + //We count the elapsed time using a simple counter instead of the high + //resolution timebase for efficieny reasons. The call to fetch the time + //requires a user-kernel transition which has a large overhead compared + //to a simple mem read. As a tradeoff, we deal with a less precise timeout. + size_t approx_us_elapsed = 0; + while ( + nirio_status_not_fatal(status) && + (_expected_xfer_count > actual_xfer_count) && + approx_us_elapsed++ < std::max<size_t>(MIN_TIMEOUT_IN_US, timeout_ms * 1000) + ) { + boost::this_thread::sleep(boost::posix_time::microseconds(1)); + nirio_status_chain(_get_transfer_count(actual_xfer_count), status); + } + + if (_expected_xfer_count > actual_xfer_count) { + nirio_status_chain(NiRio_Status_CommunicationTimeout, status); + } + + return status; +} + +template <> +inline datatype_info_t nirio_fifo<int8_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_I8, 1); +} + +template <> +inline datatype_info_t nirio_fifo<int16_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_I16, 2); +} + +template <> +inline datatype_info_t nirio_fifo<int32_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_I32, 4); +} + +template <> +inline datatype_info_t nirio_fifo<int64_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_I64, 8); +} + +template <> +inline datatype_info_t nirio_fifo<uint8_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_U8, 1); +} + +template <> +inline datatype_info_t nirio_fifo<uint16_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_U16, 2); +} + +template <> +inline datatype_info_t nirio_fifo<uint32_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_U32, 4); +} + +template <> +inline datatype_info_t nirio_fifo<uint64_t>::_get_datatype_info() +{ + return datatype_info_t(SCALAR_U64, 8); +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif diff --git a/host/include/uhd/transport/nirio/nirio_quirks.h b/host/include/uhd/transport/nirio/nirio_quirks.h new file mode 100644 index 000000000..326eeeb8c --- /dev/null +++ b/host/include/uhd/transport/nirio/nirio_quirks.h @@ -0,0 +1,78 @@ +// +// Copyright 2013-2014 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_UHD_TRANSPORT_NIRIO_NIRIO_QUIRKS_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_QUIRKS_H + +#include <set> +#include <uhd/utils/log.hpp> + +//Quirk#1: We need to verify RX zero-copy data transfers from the RIO +// driver if we are in full duplex mode. +// This option allows disabling this quirk by compiling it out. +#define UHD_NIRIO_RX_FIFO_XFER_CHECK_EN 1 + +namespace uhd { namespace niusrprio { + +class nirio_quirks { +public: + nirio_quirks() : _tx_stream_count(0) { + } + + UHD_INLINE void register_tx_streams(const uint32_t tx_stream_indices[]) { + for (size_t i = 0; i < sizeof(tx_stream_indices)/sizeof(*tx_stream_indices); i++) { + _tx_stream_fifo_indices.insert(tx_stream_indices[i]); + } + } + + UHD_INLINE void add_tx_fifo(uint32_t index) { + if (_tx_stream_fifo_indices.find(index) != _tx_stream_fifo_indices.end()) { + if (_tx_stream_count == 0) { + UHD_LOG << "NI-RIO RX FIFO Transfer Check Quirk Enabled."; + } + _tx_stream_count++; + } + } + + UHD_INLINE void remove_tx_fifo(uint32_t index) { + if (_tx_stream_fifo_indices.find(index) != _tx_stream_fifo_indices.end()) { + _tx_stream_count--; + if (_tx_stream_count == 0) { + UHD_LOG << "NI-RIO RX FIFO Transfer Check Quirk Disabled."; + } + } + } + + //Quirk#1: We need to verify RX zero-copy data transfers from the RIO + // driver if we are in full duplex mode. + // This function returns true if the quirk is enabled for the + // current uhd_device configuration (dynamic) + UHD_INLINE bool rx_fifo_xfer_check_en() const { + //This function must be as fast as possible because it is in a high + //throughput data path + return _tx_stream_count > 0; + } + +private: + std::set<uint32_t> _tx_stream_fifo_indices; + size_t _tx_stream_count; +}; + +}} + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_QUIRKS_H */ diff --git a/host/include/uhd/transport/nirio/nirio_resource_manager.h b/host/include/uhd/transport/nirio/nirio_resource_manager.h new file mode 100644 index 000000000..a10b3d532 --- /dev/null +++ b/host/include/uhd/transport/nirio/nirio_resource_manager.h @@ -0,0 +1,145 @@ +// +// Copyright 2013 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_UHD_TRANSPORT_NIRIO_NIRIO_RESOURCE_MANAGER_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_RESOURCE_MANAGER_H + +#include <uhd/transport/nirio/nirio_fifo.h> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <vector> +#include <map> +#include <string> + +namespace uhd { namespace niusrprio +{ +enum register_direction_t { + CONTROL, + INDICATOR +}; + +struct nirio_register_info_t { + nirio_register_info_t( + uint32_t arg_offset, + const char* arg_name, + register_direction_t arg_direction) : + offset(arg_offset), + name(arg_name), + direction(arg_direction) + {} + + uint32_t offset; + std::string name; + register_direction_t direction; +}; + +typedef std::vector<nirio_register_info_t> nirio_register_info_vtr; + +struct nirio_fifo_info_t { + nirio_fifo_info_t( + uint32_t arg_channel, + const char* arg_name, + fifo_direction_t arg_direction, + uint32_t arg_base_addr, + uint32_t arg_depth, + nirio_scalar_t arg_scalar_type, + uint32_t arg_width, + uint32_t arg_version) : + channel(arg_channel), + name(arg_name), + direction(arg_direction), + base_addr(arg_base_addr), + depth(arg_depth), + scalar_type(arg_scalar_type), + width(arg_width), + version(arg_version) + {} + + uint32_t channel; + std::string name; + fifo_direction_t direction; + uint32_t base_addr; + uint32_t depth; + nirio_scalar_t scalar_type; + uint32_t width; + uint32_t version; +}; + +typedef std::vector<nirio_fifo_info_t> nirio_fifo_info_vtr; + + +class nirio_resource_manager +{ +public: + nirio_resource_manager(niriok_proxy& proxy); + virtual ~nirio_resource_manager(); + + nirio_status initialize(const nirio_register_info_vtr& reg_info_vtr, const nirio_fifo_info_vtr& fifo_info_vtr); + void finalize(); + + nirio_status get_register_offset(const char* register_name, uint32_t& offset); + + template<typename data_t> + nirio_status create_tx_fifo(const char* fifo_name, boost::shared_ptr< nirio_fifo<data_t> >& fifo) + { + nirio_fifo_info_t* fifo_info_ptr = _lookup_fifo_info(fifo_name); + if (fifo_info_ptr) { + fifo.reset(new nirio_fifo<data_t>(_kernel_proxy, OUTPUT_FIFO, fifo_info_ptr->name, fifo_info_ptr->channel)); + } else { + return NiRio_Status_ResourceNotFound; + } + + if (fifo->get_channel() != fifo_info_ptr->channel) return NiRio_Status_InvalidParameter; + if (fifo->get_scalar_type() != fifo_info_ptr->scalar_type) return NiRio_Status_InvalidParameter; + + return NiRio_Status_Success; + } + + template<typename data_t> + nirio_status create_rx_fifo(const char* fifo_name, boost::shared_ptr< nirio_fifo<data_t> >& fifo) + { + nirio_fifo_info_t* fifo_info_ptr = _lookup_fifo_info(fifo_name); + if (fifo_info_ptr) { + fifo.reset(new nirio_fifo<data_t>(_kernel_proxy, INPUT_FIFO, fifo_info_ptr->name, fifo_info_ptr->channel)); + } else { + return NiRio_Status_ResourceNotFound; + } + + if (fifo->get_channel() != fifo_info_ptr->channel) return NiRio_Status_InvalidParameter; + if (fifo->get_scalar_type() != fifo_info_ptr->scalar_type) return NiRio_Status_InvalidParameter; + + return NiRio_Status_Success; + } + +private: + nirio_resource_manager (const nirio_resource_manager&); + nirio_resource_manager& operator = (const nirio_resource_manager&); + + typedef std::map<const std::string, nirio_fifo_info_t> fifo_info_map_t; + typedef std::map<const std::string, nirio_register_info_t> register_info_map_t; + + nirio_status _add_fifo_resource(const nirio_fifo_info_t& fifo_info); + nirio_status _set_driver_config(); + nirio_fifo_info_t* _lookup_fifo_info(const char* fifo_name); + + niriok_proxy& _kernel_proxy; + fifo_info_map_t _fifo_info_map; + register_info_map_t _reg_info_map; +}; + +}} +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_RESOURCE_MANAGER_H */ diff --git a/host/include/uhd/transport/nirio/niriok_proxy.h b/host/include/uhd/transport/nirio/niriok_proxy.h new file mode 100644 index 000000000..a6b6183d1 --- /dev/null +++ b/host/include/uhd/transport/nirio/niriok_proxy.h @@ -0,0 +1,160 @@ +// +// Copyright 2013-2014 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_UHD_TRANSPORT_NIRIO_NIRIO_INTERFACE_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_INTERFACE_H + +#include <boost/smart_ptr.hpp> +#include <boost/noncopyable.hpp> +#include <uhd/transport/nirio/nirio_driver_iface.h> +#include <uhd/transport/nirio/nirio_quirks.h> + +namespace uhd { namespace niusrprio +{ + enum nirio_version_t { CURRENT, OLDEST_COMPATIBLE }; + + enum nirio_device_attr_32_t { + INTERFACE_NUMBER = 1UL, + PRODUCT_NUMBER = 2UL, + VENDOR_NUMBER = 3UL, + SERIAL_NUMBER = 4UL, + BUS_NUMBER = 10UL, + DEVICE_NUMBER = 11UL, + FUNCTION_NUMBER = 12UL, + CURRENT_VERSION = 14UL, + OLDEST_COMPATIBLE_VERSION = 15UL, + ADDRESS_SPACE = 25UL, + IS_FPGA_PROGRAMMED = 48UL, + DEFAULT_FPGA_SIGNATURE_OFFSET = 53UL, + DEFAULT_FPGA_RESET_OFFSET = 54UL, + DEFAULT_FPGA_RESET_SIZE = 55UL, + DEFAULT_FPGA_CONTROL_OFFSET = 56UL, + DEFAULT_FPGA_INTERRUPT_OFFSET = 57UL, + }; + + enum nirio_device_attr_str_t { + PRODUCT_NAME = 0UL, + FPGA_TARGET_CLASS = 6UL, + SAVED_BITFILE = 7UL, + }; + + enum nirio_addr_space_t { + INVALID = 0, + BUS_INTERFACE = 1, + FPGA = 2, + BAR_WINDOW = 3, + }; + + + class UHD_API niriok_proxy : public boost::noncopyable { + public: + typedef boost::shared_ptr<niriok_proxy> sptr; + + niriok_proxy(); + virtual ~niriok_proxy(); + + //File operations + nirio_status open(const std::string& interface_path); + void close(void); + + nirio_status reset(); + + inline uint32_t get_interface_num() { return _interface_num; } + + nirio_status get_cached_session( + uint32_t& session); + + nirio_status get_version( + nirio_version_t type, + uint32_t& major, + uint32_t& upgrade, + uint32_t& maintenance, + char& phase, + uint32_t& build); + + nirio_status sync_operation( + const void *writeBuffer, + size_t writeBufferLength, + void *readBuffer, + size_t readBufferLength); + + nirio_status get_attribute( + const nirio_device_attr_32_t attribute, + uint32_t& attrValue); + + nirio_status get_attribute( + const nirio_device_attr_str_t attribute, + char* buf, + const uint32_t bufLen, + uint32_t& stringLen); + + nirio_status set_attribute( + const nirio_device_attr_32_t attribute, + const uint32_t value); + + nirio_status set_attribute( + const nirio_device_attr_str_t attribute, + const char* const buffer); + + nirio_status peek(uint32_t offset, uint32_t& value); + + nirio_status peek(uint32_t offset, uint64_t& value); + + nirio_status poke(uint32_t offset, const uint32_t& value); + + nirio_status poke(uint32_t offset, const uint64_t& value); + + nirio_status map_fifo_memory( + uint32_t fifo_instance, + size_t size, + nirio_driver_iface::rio_mmap_t& map); + + nirio_status unmap_fifo_memory( + nirio_driver_iface::rio_mmap_t& map); + + nirio_quirks& get_rio_quirks() { + return _rio_quirks; + } + + private: //Members + nirio_driver_iface::rio_dev_handle_t _device_handle; + uint32_t _interface_num; + nirio_quirks _rio_quirks; + }; + + class niriok_scoped_addr_space : public boost::noncopyable { + public: + explicit niriok_scoped_addr_space(niriok_proxy& proxy, nirio_addr_space_t addr_space, nirio_status& status) : + driver_proxy(proxy) + { + cache_status = driver_proxy.get_attribute(ADDRESS_SPACE, cached_addr_space); + nirio_status_chain(driver_proxy.set_attribute(ADDRESS_SPACE, addr_space), status); + } + + ~niriok_scoped_addr_space() { + if (nirio_status_not_fatal(cache_status)) + driver_proxy.set_attribute(ADDRESS_SPACE, cached_addr_space); + } + + private: + niriok_proxy& driver_proxy; + uint32_t cached_addr_space; + nirio_status cache_status; + }; +}} + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIRIO_INTERFACE_H */ diff --git a/host/include/uhd/transport/nirio/niusrprio_session.h b/host/include/uhd/transport/nirio/niusrprio_session.h new file mode 100644 index 000000000..c9a61ae76 --- /dev/null +++ b/host/include/uhd/transport/nirio/niusrprio_session.h @@ -0,0 +1,125 @@ +// +// Copyright 2013 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_UHD_TRANSPORT_NIRIO_NIUSRPRIO_SESSION_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_NIUSRPRIO_SESSION_H + +#include <uhd/transport/nirio/rpc/usrprio_rpc_client.hpp> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <uhd/transport/nirio/nirio_resource_manager.h> +#include <uhd/transport/nirio/nifpga_lvbitx.h> +#include <boost/noncopyable.hpp> +#include <boost/smart_ptr.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <string> + +namespace uhd { namespace niusrprio { + +class UHD_API niusrprio_session : private boost::noncopyable +{ +public: + typedef boost::shared_ptr<niusrprio_session> sptr; + typedef uhd::usrprio_rpc::usrprio_device_info device_info; + typedef uhd::usrprio_rpc::usrprio_device_info_vtr device_info_vtr; + + static nirio_status enumerate( + const std::string& rpc_port_name, + device_info_vtr& device_info_vtr); + + niusrprio_session( + const std::string& resource_name, + const std::string& port_name); + virtual ~niusrprio_session(); + + nirio_status open( + nifpga_lvbitx::sptr lvbitx, + bool force_download = false); + + void close(bool skip_reset = false); + + nirio_status reset(); + + template<typename data_t> + nirio_status create_tx_fifo( + const char* fifo_name, + boost::shared_ptr< nirio_fifo<data_t> >& fifo) + { + if (!_session_open) return NiRio_Status_ResourceNotInitialized; + return _resource_manager.create_tx_fifo(fifo_name, fifo); + } + + template<typename data_t> + nirio_status create_tx_fifo( + uint32_t fifo_instance, + boost::shared_ptr< nirio_fifo<data_t> >& fifo) + { + if ((size_t)fifo_instance >= _lvbitx->get_output_fifo_count()) return NiRio_Status_InvalidParameter; + return create_tx_fifo(_lvbitx->get_output_fifo_names()[fifo_instance], fifo); + } + + template<typename data_t> + nirio_status create_rx_fifo( + const char* fifo_name, + boost::shared_ptr< nirio_fifo<data_t> >& fifo) + { + if (!_session_open) return NiRio_Status_ResourceNotInitialized; + return _resource_manager.create_rx_fifo(fifo_name, fifo); + } + + template<typename data_t> + nirio_status create_rx_fifo( + uint32_t fifo_instance, + boost::shared_ptr< nirio_fifo<data_t> >& fifo) + { + if ((size_t)fifo_instance >= _lvbitx->get_input_fifo_count()) return NiRio_Status_InvalidParameter; + return create_rx_fifo(_lvbitx->get_input_fifo_names()[fifo_instance], fifo); + } + + niriok_proxy& get_kernel_proxy() { + return _riok_proxy; + } + + nirio_status download_bitstream_to_flash(const std::string& bitstream_path); + + //Static + static niriok_proxy::sptr create_kernel_proxy( + const std::string& resource_name, + const std::string& rpc_port_name); + +private: + nirio_status _verify_signature(); + std::string _read_bitstream_checksum(); + nirio_status _write_bitstream_checksum(const std::string& checksum); + nirio_status _wait_for_device_available(); + + std::string _resource_name; + nifpga_lvbitx::sptr _lvbitx; + std::string _interface_path; + bool _session_open; + niriok_proxy _riok_proxy; + nirio_resource_manager _resource_manager; + usrprio_rpc::usrprio_rpc_client _rpc_client; + boost::recursive_mutex _session_mutex; + + static const uint32_t SESSION_LOCK_TIMEOUT_IN_MS = 3000; + static const uint32_t SESSION_LOCK_RETRY_INT_IN_MS = 500; +}; + +}} + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIUSRPRIO_SESSION_H */ diff --git a/host/include/uhd/transport/nirio/rpc/rpc_client.hpp b/host/include/uhd/transport/nirio/rpc/rpc_client.hpp new file mode 100644 index 000000000..f90034e37 --- /dev/null +++ b/host/include/uhd/transport/nirio/rpc/rpc_client.hpp @@ -0,0 +1,94 @@ +// +// Copyright 2013 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_RPC_CLIENT_HPP +#define INCLUDED_RPC_CLIENT_HPP + +#include <boost/asio.hpp> +#include <boost/smart_ptr.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/condition_variable.hpp> +#include "rpc_common.hpp" +#include <uhd/utils/log.hpp> + +namespace uhd { namespace usrprio_rpc { + +class rpc_client : private boost::noncopyable +{ +public: + static const boost::uint32_t CURRENT_VERSION = 1; + static const boost::uint32_t OLDEST_COMPATIBLE_VERSION = 1; + + rpc_client( + const std::string& server, + const std::string& port, + boost::uint32_t process_id, + boost::uint32_t host_id); + ~rpc_client(); + + const boost::system::error_code& call( + func_id_t func_id, + const func_args_writer_t& in_args, + func_args_reader_t &out_args, + boost::posix_time::milliseconds timeout); + + inline const boost::system::error_code& status() const { + return _exec_err; + } + + /* [Possible boost::system::error_code values] + * boost::asio::error::connection_aborted: Network connection failure + * boost::asio::error::eof: Network connection closed cleanly + * boost::asio::error::connection_refused: Software handshake failure (version mismatch, etc) + * boost::asio::error::timed_out: RPC call timed out + * boost::asio::error::operation_aborted: RPC call aborted but connection alive + */ + +private: + void _handle_response_hdr(const boost::system::error_code& err, size_t transferred, size_t expected); + void _handle_response_data(const boost::system::error_code& err, size_t transferred, size_t expected); + void _wait_for_next_response_header(); + + inline void _stop_io_service() { + if (_io_service_thread.get()) { + UHD_LOG << "rpc_client stopping..." << std::endl; + _io_service.stop(); + _io_service_thread->join(); + _io_service_thread.reset(); + UHD_LOG << "rpc_client stopped." << std::endl; + } + } + + //Services + boost::asio::io_service _io_service; + boost::scoped_ptr<boost::thread> _io_service_thread; + boost::asio::ip::tcp::socket _socket; + //Handshake info + hshake_args_t _hshake_args_client; + hshake_args_t _hshake_args_server; + //In-out function args + func_xport_buf_t _request; + func_xport_buf_t _response; + //Synchronization + boost::mutex _mutex; + boost::condition_variable _exec_gate; + boost::system::error_code _exec_err; +}; + +}} + +#endif /* INCLUDED_RPC_CLIENT_HPP */ diff --git a/host/include/uhd/transport/nirio/rpc/rpc_common.hpp b/host/include/uhd/transport/nirio/rpc/rpc_common.hpp new file mode 100644 index 000000000..ea5b3337d --- /dev/null +++ b/host/include/uhd/transport/nirio/rpc/rpc_common.hpp @@ -0,0 +1,158 @@ +// +// Copyright 2013 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_RPC_COMMON_HPP +#define INCLUDED_RPC_COMMON_HPP + +#define USE_BINARY_ARCHIVE 0 + +#include <string> +#include <iostream> +#include <sstream> +#include <vector> +#if (USE_BINARY_ARCHIVE) + #include <boost/archive/binary_oarchive.hpp> + #include <boost/archive/binary_iarchive.hpp> +#else + #include <boost/archive/text_oarchive.hpp> + #include <boost/archive/text_iarchive.hpp> +#endif + +namespace uhd { namespace usrprio_rpc { + +//[Over-the-wire] IDs +typedef boost::int32_t func_id_t; +typedef boost::uint64_t client_id_t; + +#define build_client_id(host_id, process_id) \ + ((static_cast<boost::uint64_t>(host_id) << 32) | static_cast<boost::uint64_t>(process_id)) +#define get_process_id_from_client_id(client_id) \ + (static_cast<boost::int32_t>(client_id)) +#define get_host_id_from_client_id(client_id) \ + (static_cast<boost::uint32_t>(client_id >> 32)) + +//[Over-the-wire] Handshake format +struct hshake_args_t { + boost::uint32_t version; + boost::uint32_t oldest_comp_version; + boost::int32_t boost_archive_version; + client_id_t client_id; +}; + +//[Over-the-wire] Header for RPC request and response +class func_args_header_t { +public: + func_id_t func_id; + client_id_t client_id; + boost::uint32_t func_args_size; + + static bool match_function(const func_args_header_t& a, const func_args_header_t& b) { + return ((a.func_id == b.func_id) && (a.client_id == b.client_id)); + } +}; + +//[Internal] Storage for RPC header and arguments +class func_xport_buf_t { +public: + func_args_header_t header; + std::vector<char> data; +}; + +//[Internal] Serializer for RPC input parameters +class func_args_writer_t { +public: + func_args_writer_t() : _stream(), _archive(_stream, boost::archive::no_header) {} + + template<typename data_t> + void push(const data_t& d) { + _archive << d; + } + + template<typename data_t> + func_args_writer_t& operator<< (const data_t& data) { + push(data); + return *this; + } + + void store(std::vector<char>& data) const { + const std::string& str = _stream.str(); + data.resize(str.length()); + data.assign((char*)str.c_str(), ((char*)str.c_str()) + str.length()); + } + +private: + std::ostringstream _stream; +#if (USE_BINARY_ARCHIVE) + boost::archive::binary_oarchive _archive; +#else + boost::archive::text_oarchive _archive; +#endif +}; + +//[Internal] Deserializer for RPC output parameters +class func_args_reader_t { +public: + func_args_reader_t() : _stream(), _archive() {} + + template<typename data_t> + void pull(data_t& d) const { + if (_archive) (*_archive) >> d; + } + + template<typename data_t> + const func_args_reader_t& operator>> (data_t& data) const { + pull(data); + return *this; + } + + void load(const std::vector<char>& data) { + _stream.str(std::string(data.begin(), data.end())); +#if (USE_BINARY_ARCHIVE) + _archive.reset(new boost::archive::binary_iarchive(_stream, boost::archive::no_header)); +#else + _archive.reset(new boost::archive::text_iarchive(_stream, boost::archive::no_header)); +#endif + } + +private: + std::istringstream _stream; +#if (USE_BINARY_ARCHIVE) + boost::scoped_ptr<boost::archive::binary_iarchive> _archive; +#else + boost::scoped_ptr<boost::archive::text_iarchive> _archive; +#endif +}; + +class boost_serialization_archive_utils { +public: + static boost::int32_t get_version() { + #if (USE_BINARY_ARCHIVE) + typedef boost::archive::binary_oarchive archive_t; + #else + typedef boost::archive::text_oarchive archive_t; + #endif + std::ostringstream stream; + archive_t dummy_archive(stream, boost::archive::no_header); + return static_cast<boost::int32_t>(dummy_archive.get_library_version()); + } +}; + +}} + +#undef USE_BINARY_ARCHIVE + +#endif /* INCLUDED_RPC_COMMON_HPP */ diff --git a/host/include/uhd/transport/nirio/rpc/usrprio_rpc_client.hpp b/host/include/uhd/transport/nirio/rpc/usrprio_rpc_client.hpp new file mode 100644 index 000000000..4b205cceb --- /dev/null +++ b/host/include/uhd/transport/nirio/rpc/usrprio_rpc_client.hpp @@ -0,0 +1,70 @@ +// +// Copyright 2013 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_USRPRIO_RPC_CLIENT_HPP +#define INCLUDED_USRPRIO_RPC_CLIENT_HPP + +#include <uhd/transport/nirio/rpc/rpc_common.hpp> +#include <uhd/transport/nirio/rpc/rpc_client.hpp> +#include <uhd/transport/nirio/rpc/usrprio_rpc_common.hpp> +#include <uhd/transport/nirio/status.h> + +namespace uhd { namespace usrprio_rpc { + +class UHD_API usrprio_rpc_client { +public: + usrprio_rpc_client( + std::string server, + std::string port); + ~usrprio_rpc_client(); + + inline void set_rpc_timeout(boost::posix_time::milliseconds timeout_in_ms) { + _timeout = timeout_in_ms; + } + + inline nirio_status get_ctor_status() { + return _ctor_status; + } + + nirio_status niusrprio_enumerate( + NIUSRPRIO_ENUMERATE_ARGS); + nirio_status niusrprio_open_session( + NIUSRPRIO_OPEN_SESSION_ARGS); + nirio_status niusrprio_close_session( + NIUSRPRIO_CLOSE_SESSION_ARGS); + nirio_status niusrprio_reset_device( + NIUSRPRIO_RESET_SESSION_ARGS); + nirio_status niusrprio_download_bitstream_to_fpga( + NIUSRPRIO_DOWNLOAD_BITSTREAM_TO_FPGA_ARGS); + nirio_status niusrprio_get_interface_path( + NIUSRPRIO_GET_INTERFACE_PATH_ARGS); + nirio_status niusrprio_download_fpga_to_flash( + NIUSRPRIO_DOWNLOAD_FPGA_TO_FLASH_ARGS); + + static const boost::int64_t DEFAULT_TIMEOUT_IN_MS = 5000; + +private: + static nirio_status _boost_error_to_nirio_status(const boost::system::error_code& err); + + rpc_client _rpc_client; + boost::posix_time::milliseconds _timeout; + nirio_status _ctor_status; +}; + +}} + +#endif /* INCLUDED_USRPRIO_RPC_CLIENT_HPP */ diff --git a/host/include/uhd/transport/nirio/rpc/usrprio_rpc_common.hpp b/host/include/uhd/transport/nirio/rpc/usrprio_rpc_common.hpp new file mode 100644 index 000000000..362d9a174 --- /dev/null +++ b/host/include/uhd/transport/nirio/rpc/usrprio_rpc_common.hpp @@ -0,0 +1,85 @@ +// +// Copyright 2013 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_USRPRIO_RPC_COMMON_HPP +#define INCLUDED_USRPRIO_RPC_COMMON_HPP + +#include <uhd/transport/nirio/rpc/rpc_common.hpp> + +namespace uhd { namespace usrprio_rpc { + +//Function IDs + +static const func_id_t NIUSRPRIO_FUNC_BASE = 0x100; + +static const func_id_t NIUSRPRIO_ENUMERATE = NIUSRPRIO_FUNC_BASE + 0; +static const func_id_t NIUSRPRIO_OPEN_SESSION = NIUSRPRIO_FUNC_BASE + 1; +static const func_id_t NIUSRPRIO_CLOSE_SESSION = NIUSRPRIO_FUNC_BASE + 2; +static const func_id_t NIUSRPRIO_RESET_SESSION = NIUSRPRIO_FUNC_BASE + 3; +static const func_id_t NIUSRPRIO_DOWNLOAD_BITSTREAM_TO_FPGA = NIUSRPRIO_FUNC_BASE + 4; +static const func_id_t NIUSRPRIO_GET_INTERFACE_PATH = NIUSRPRIO_FUNC_BASE + 5; +static const func_id_t NIUSRPRIO_DOWNLOAD_FPGA_TO_FLASH = NIUSRPRIO_FUNC_BASE + 6; + +//Function Args + +struct usrprio_device_info { + boost::uint32_t interface_num; + std::string resource_name; + std::string pcie_serial_num; + std::string interface_path; + + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + if (version || !version) { //Suppress unused warning + ar & interface_num; + ar & resource_name; + ar & pcie_serial_num; + ar & interface_path; + } + } +}; +typedef std::vector<usrprio_device_info> usrprio_device_info_vtr; + +#define NIUSRPRIO_ENUMERATE_ARGS \ + usrprio_device_info_vtr& device_info_vtr + +#define NIUSRPRIO_OPEN_SESSION_ARGS \ + const std::string& resource, \ + const std::string& path, \ + const std::string& signature, \ + const boost::uint16_t& download_fpga + +#define NIUSRPRIO_CLOSE_SESSION_ARGS \ + const std::string& resource + +#define NIUSRPRIO_RESET_SESSION_ARGS \ + const std::string& resource + +#define NIUSRPRIO_DOWNLOAD_BITSTREAM_TO_FPGA_ARGS \ + const std::string& resource + +#define NIUSRPRIO_GET_INTERFACE_PATH_ARGS \ + const std::string& resource, \ + std::string& interface_path + +#define NIUSRPRIO_DOWNLOAD_FPGA_TO_FLASH_ARGS \ + const std::string& resource, \ + const std::string& bitstream_path +}} + +#endif /* INCLUDED_USRPRIO_RPC_COMMON_HPP */ diff --git a/host/include/uhd/transport/nirio/status.h b/host/include/uhd/transport/nirio/status.h new file mode 100644 index 000000000..e4117ac73 --- /dev/null +++ b/host/include/uhd/transport/nirio/status.h @@ -0,0 +1,65 @@ +// +// Copyright 2013 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_UHD_TRANSPORT_NIRIO_STATUS_H +#define INCLUDED_UHD_TRANSPORT_NIRIO_STATUS_H + +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <string> +#include <uhd/exception.hpp> + +#define ENABLE_EXTENDED_ERROR_INFO false + +typedef int32_t nirio_status; + +namespace uhd { namespace niusrprio { +struct nirio_err_info { + nirio_err_info(nirio_status arg_code, const char* arg_msg): code(arg_code), msg(arg_msg) {} + + nirio_status code; + const char* msg; + + static const nirio_err_info NIRIO_ERROR_TABLE[]; + static const size_t NIRIO_ERROR_TABLE_SIZE; +}; + +const std::string lookup_err_msg(nirio_status code); + +void nirio_status_to_exception(const nirio_status& status, const std::string& message); +}} + +#define nirio_status_fatal(status) ((status) < 0) +#define nirio_status_not_fatal(status) ((status) >= 0) + +#define nirio_status_chain(func, status) \ + if (nirio_status_not_fatal(status)) { \ + status = (func); \ + if (ENABLE_EXTENDED_ERROR_INFO && nirio_status_fatal(status)) { \ + fprintf(stderr,"ERROR: The following function call returned status code %d\n%s\n%s:%d\n",status,#func,__FILE__,__LINE__); \ + } \ + } \ + + +#define NIRIO_ERR_INFO(CONST_NAME, ERR_CODE, ERR_MSG) \ + static const nirio_status CONST_NAME = ERR_CODE; +#include "nirio_err_template.h" +#undef NIRIO_ERR_INFO + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_STATUS_H */ diff --git a/host/include/uhd/transport/nirio_zero_copy.hpp b/host/include/uhd/transport/nirio_zero_copy.hpp new file mode 100644 index 000000000..5b16b1975 --- /dev/null +++ b/host/include/uhd/transport/nirio_zero_copy.hpp @@ -0,0 +1,43 @@ +// +// Copyright 2013 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_UHD_TRANSPORT_NIRIO_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_NIRIO_ZERO_COPY_HPP + +#include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/config.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/device_addr.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +class UHD_API nirio_zero_copy : public virtual zero_copy_if{ +public: + typedef boost::shared_ptr<nirio_zero_copy> sptr; + + static sptr make( + uhd::niusrprio::niusrprio_session::sptr fpga_session, + const uint32_t instance, + const zero_copy_xport_params &default_buff_args, + const device_addr_t &hints = device_addr_t() + ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_ZERO_COPY_HPP */ diff --git a/host/include/uhd/transport/tcp_zero_copy.hpp b/host/include/uhd/transport/tcp_zero_copy.hpp new file mode 100644 index 000000000..a9878a396 --- /dev/null +++ b/host/include/uhd/transport/tcp_zero_copy.hpp @@ -0,0 +1,57 @@ +// +// Copyright 2010-2013 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_UHD_TRANSPORT_TCP_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_TCP_ZERO_COPY_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/device_addr.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +/*! + * The zero copy TCP transport. + * This transport provides the uhd zero copy interface + * on top of a standard tcp socket from boost asio. + */ +struct UHD_API tcp_zero_copy : public virtual zero_copy_if +{ + /*! + * Make a new zero copy TCP transport: + * This transport is for sending and receiving + * between this host and a single endpoint. + * The primary usage for this transport will be data transactions. + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + * \param hints optional parameters to pass to the underlying transport + */ + static zero_copy_if::sptr make( + const std::string &addr, + const std::string &port, + const device_addr_t &hints = device_addr_t() + ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_TCP_ZERO_COPY_HPP */ diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index bbba97b21..8fb5115c2 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -37,6 +37,11 @@ namespace uhd{ namespace transport{ */ class UHD_API udp_zero_copy : public virtual zero_copy_if{ public: + struct buff_params { + size_t recv_buff_size; + size_t send_buff_size; + }; + typedef boost::shared_ptr<udp_zero_copy> sptr; /*! @@ -56,6 +61,8 @@ public: static sptr make( const std::string &addr, const std::string &port, + const zero_copy_xport_params &default_buff_args, + udp_zero_copy::buff_params& buff_params_out, const device_addr_t &hints = device_addr_t() ); }; diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 40d7b8c59..9ff3042aa 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -29,7 +29,14 @@ namespace uhd{ namespace transport{ //! Simple managed buffer with release interface class UHD_API managed_buffer{ public: - managed_buffer(void):_ref_count(0),_buffer(NULL),_length(0){} + managed_buffer(void):_ref_count(0),_buffer(NULL),_length(0) + { +#ifdef UHD_TXRX_DEBUG_PRINTS + _mb_num = s_buffer_count; + // From Boost website: atomic_count seems only to have precrement operator. + ++s_buffer_count; +#endif + } virtual ~managed_buffer(void) {} @@ -76,9 +83,27 @@ namespace uhd{ namespace transport{ boost::detail::atomic_count _ref_count; typedef boost::intrusive_ptr<managed_buffer> sptr; + int ref_count(){ + return (int) _ref_count; + } + +#ifdef UHD_TXRX_DEBUG_PRINTS + int num() const{ + return _mb_num; + } +#endif + protected: void *_buffer; size_t _length; +#ifdef UHD_TXRX_DEBUG_PRINTS + int _mb_num; +#endif + + private: +#ifdef UHD_TXRX_DEBUG_PRINTS + static boost::detail::atomic_count s_buffer_count; +#endif }; UHD_INLINE void intrusive_ptr_add_ref(managed_buffer *p){ @@ -110,6 +135,16 @@ namespace uhd{ namespace transport{ }; /*! + * Transport parameters + */ + struct zero_copy_xport_params { + size_t recv_frame_size; + size_t send_frame_size; + size_t num_recv_frames; + size_t num_send_frames; + }; + + /*! * A zero-copy interface for transport objects. * Provides a way to get send and receive buffers * with memory managed by the transport object. @@ -119,6 +154,11 @@ namespace uhd{ namespace transport{ typedef boost::shared_ptr<zero_copy_if> sptr; /*! + * Clean up tasks before releasing the transport object. + */ + virtual ~zero_copy_if() {}; + + /*! * Get a new receive buffer from this transport object. * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 788999900..6a79720d0 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -30,6 +30,26 @@ namespace uhd{ * The receive routines will convert IF data headers into metadata. */ struct UHD_API rx_metadata_t{ + + //! Default constructor. + rx_metadata_t() + { + reset(); + } + + //! Reset values. + void reset() + { + has_time_spec = false; + time_spec = time_spec_t(0.0); + more_fragments = false; + fragment_offset = 0; + start_of_burst = false; + end_of_burst = false; + error_code = ERROR_CODE_NONE; + out_of_sequence = false; + } + //! Has time specification? bool has_time_spec; @@ -80,13 +100,23 @@ namespace uhd{ ERROR_CODE_LATE_COMMAND = 0x2, //! Expected another stream command. ERROR_CODE_BROKEN_CHAIN = 0x4, - //! An internal receive buffer has filled. + /*! + * An internal receive buffer has filled or a sequence error has been detected. + * So, why is this overloaded? Simple: legacy support. It would have been much cleaner + * to create a separate error code for a sequence error, but that would have broken + * legacy applications. So, the out_of_sequence flag was added to differentiate between + * the two error cases. In either case, data is missing between this time_spec and the + * and the time_spec of the next successful receive. + */ ERROR_CODE_OVERFLOW = 0x8, //! Multi-channel alignment failed. ERROR_CODE_ALIGNMENT = 0xc, //! The packet could not be parsed. ERROR_CODE_BAD_PACKET = 0xf } error_code; + + //! Out of sequence. The transport has either dropped a packet or received data out of order. + bool out_of_sequence; }; /*! diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index dd6123a9f..d1f3b4463 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -96,7 +96,7 @@ namespace uhd{ * - mode_n: Allows the user to tell the daughterboard tune code * to choose between an integer N diviver or fractional N divider. * Default is fractional N on boards that support fractional N tuning. - * Fractional N provides greater tuning acuracy at the expense of spurs. + * Fractional N provides greater tuning accuracy at the expense of spurs. * Possible options for this key: "integer" or "fractional". */ device_addr_t args; diff --git a/host/include/uhd/usrp/gps_ctrl.hpp b/host/include/uhd/usrp/gps_ctrl.hpp index abe5c37ba..bbccac8bb 100644 --- a/host/include/uhd/usrp/gps_ctrl.hpp +++ b/host/include/uhd/usrp/gps_ctrl.hpp @@ -32,7 +32,7 @@ public: typedef boost::shared_ptr<gps_ctrl> sptr; /*! - * Make a GPS config for NMEA GPS devices + * Make a GPS config for internal GPSDOs or generic NMEA GPS devices */ static sptr make(uart_iface::sptr uart); diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index d60f0e60c..5b4991202 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -339,6 +339,26 @@ public: virtual std::vector<std::string> get_clock_sources(const size_t mboard) = 0; /*! + * Send the clock source to an output connector. + * This call is only applicable on devices with reference outputs. + * By default, the reference output will be enabled for ease of use. + * This call may be used to enable or disable the output. + * \param enb true to output the clock source. + * \param mboard which motherboard to set + */ + virtual void set_clock_source_out(const bool enb, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Send the time source to an output connector. + * This call is only applicable on devices with PPS outputs. + * By default, the PPS output will be enabled for ease of use. + * This call may be used to enable or disable the output. + * \param enb true to output the time source. + * \param mboard which motherboard to set + */ + virtual void set_time_source_out(const bool enb, const size_t mboard = ALL_MBOARDS) = 0; + + /*! * Get the number of USRP motherboards in this configuration. */ virtual size_t get_num_mboards(void) = 0; @@ -856,6 +876,53 @@ public: */ virtual void set_tx_iq_balance(const std::complex<double> &correction, size_t chan = ALL_CHANS) = 0; + /******************************************************************* + * GPIO methods + ******************************************************************/ + + /*! + * Enumerate gpio banks on the specified device. + * \param mboard the motherboard index 0 to M-1 + * \return a list of string for each bank name + */ + virtual std::vector<std::string> get_gpio_banks(const size_t mboard) = 0; + + /*! + * Set a GPIO attribute on a particular GPIO bank. + * Possible attribute names: + * - CTRL - 1 for ATR mode 0 for GPIO mode + * - DDR - 1 for output 0 for input + * - OUT - GPIO output level (not ATR mode) + * - ATR_0X - ATR idle state + * - ATR_RX - ATR receive only state + * - ATR_TX - ATR transmit only state + * - ATR_XX - ATR full duplex state + * \param bank the name of a GPIO bank + * \param attr the name of a GPIO attribute + * \param value the new value for this GPIO bank + * \param mask the bit mask to effect which pins are changed + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_gpio_attr(const std::string &bank, const std::string &attr, const boost::uint32_t value, const boost::uint32_t mask = 0xffffffff, const size_t mboard = 0) = 0; + + /*! + * Get a GPIO attribute on a particular GPIO bank. + * Possible attribute names: + * - CTRL - 1 for ATR mode 0 for GPIO mode + * - DDR - 1 for output 0 for input + * - OUT - GPIO output level (not ATR mode) + * - ATR_0X - ATR idle state + * - ATR_RX - ATR receive only state + * - ATR_TX - ATR transmit only state + * - ATR_XX - ATR full duplex state + * - READBACK - readback input GPIOs + * \param bank the name of a GPIO bank + * \param attr the name of a GPIO attribute + * \param mboard the motherboard index 0 to M-1 + * \return the value set for this attribute + */ + virtual boost::uint32_t get_gpio_attr(const std::string &bank, const std::string &attr, const size_t mboard = 0) = 0; + }; }} diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index e86826435..c0991b3ce 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -30,6 +30,7 @@ UHD_INSTALL(FILES msg_task.hpp paths.hpp pimpl.hpp + platform.hpp safe_call.hpp safe_main.hpp static.hpp diff --git a/host/include/uhd/utils/platform.hpp b/host/include/uhd/utils/platform.hpp new file mode 100644 index 000000000..de778f61c --- /dev/null +++ b/host/include/uhd/utils/platform.hpp @@ -0,0 +1,36 @@ +// +// Copyright 2010,2012 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_UHD_UTILS_PLATFORM_HPP +#define INCLUDED_UHD_UTILS_PLATFORM_HPP + +#include <boost/cstdint.hpp> + +namespace uhd { + + /* Returns the process ID of the current process */ + boost::int32_t get_process_id(); + + /* Returns a unique identifier for the current machine */ + boost::uint32_t get_host_id(); + + /* Get a unique identifier for the current machine and process */ + boost::uint32_t get_process_hash(); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_PLATFORM_HPP */ diff --git a/host/include/uhd/version.hpp b/host/include/uhd/version.hpp index a62ee8285..1bb89dd84 100644 --- a/host/include/uhd/version.hpp +++ b/host/include/uhd/version.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2013 Ettus Research LLC +// Copyright 2010-2014 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 @@ * The format is oldest API compatible release - ABI compat number. * The compatibility number allows pre-release ABI to be versioned. */ -#define UHD_VERSION_ABI_STRING "3.6.0-1" +#define UHD_VERSION_ABI_STRING "3.7.0-0" namespace uhd{ |