aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/usrp/common/fw_comm_protocol.h102
-rw-r--r--host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp2
-rw-r--r--host/lib/usrp/n230/n230_cores.cpp2
-rw-r--r--host/lib/usrp/n230/n230_eeprom_manager.cpp27
-rw-r--r--host/lib/usrp/n230/n230_eeprom_manager.hpp2
-rw-r--r--host/lib/usrp/n230/n230_fw_defs.h137
-rw-r--r--host/lib/usrp/n230/n230_fw_host_iface.h128
-rw-r--r--host/lib/usrp/n230/n230_image_loader.cpp3
-rw-r--r--host/lib/usrp/n230/n230_impl.cpp76
-rw-r--r--host/lib/usrp/n230/n230_resource_manager.cpp21
-rw-r--r--host/lib/usrp/n230/n230_resource_manager.hpp7
11 files changed, 459 insertions, 48 deletions
diff --git a/host/lib/usrp/common/fw_comm_protocol.h b/host/lib/usrp/common/fw_comm_protocol.h
new file mode 100644
index 000000000..14adb33a9
--- /dev/null
+++ b/host/lib/usrp/common/fw_comm_protocol.h
@@ -0,0 +1,102 @@
+//
+// Copyright 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_FW_COMM_PROTOCOL
+#define INCLUDED_FW_COMM_PROTOCOL
+
+#include <stdint.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+/*!
+ * Structs and constants for communication between firmware and host.
+ * This header is shared by the firmware and host code.
+ * Therefore, this header may only contain valid C code.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FW_COMM_PROTOCOL_SIGNATURE 0xACE3
+#define FW_COMM_PROTOCOL_VERSION 0
+#define FW_COMM_MAX_DATA_WORDS 16
+#define FW_COMM_PROTOCOL_MTU 256
+
+#define FW_COMM_FLAGS_ACK 0x00000001
+#define FW_COMM_FLAGS_CMD_MASK 0x00000FF0
+#define FW_COMM_FLAGS_ERROR_MASK 0xFF000000
+
+#define FW_COMM_CMD_ECHO 0x00000000
+#define FW_COMM_CMD_POKE32 0x00000010
+#define FW_COMM_CMD_PEEK32 0x00000020
+#define FW_COMM_CMD_BLOCK_POKE32 0x00000030
+#define FW_COMM_CMD_BLOCK_PEEK32 0x00000040
+
+#define FW_COMM_ERR_PKT_ERROR 0x80000000
+#define FW_COMM_ERR_CMD_ERROR 0x40000000
+#define FW_COMM_ERR_SIZE_ERROR 0x20000000
+
+#define FW_COMM_GENERATE_ID(prod) ((((uint32_t) FW_COMM_PROTOCOL_SIGNATURE) << 0) | \
+ (((uint32_t) prod) << 16) | \
+ (((uint32_t) FW_COMM_PROTOCOL_VERSION) << 24))
+
+#define FW_COMM_GET_PROTOCOL_SIG(id) ((uint16_t)(id & 0xFFFF))
+#define FW_COMM_GET_PRODUCT_ID(id) ((uint8_t)(id >> 16))
+#define FW_COMM_GET_PROTOCOL_VER(id) ((uint8_t)(id >> 24))
+
+typedef struct
+{
+ uint32_t id; //Protocol and device identifier
+ uint32_t flags; //Holds commands and ack messages
+ uint32_t sequence; //Sequence number (specific to FW communication transactions)
+ uint32_t data_words; //Number of data words in payload
+ uint32_t addr; //Address field for the command in flags
+ uint32_t data[FW_COMM_MAX_DATA_WORDS]; //Data field for the command in flags
+} fw_comm_pkt_t;
+
+#ifdef __cplusplus
+} //extern "C"
+#endif
+
+// The following definitions are only useful in firmware. Exclude in host code.
+#ifndef __cplusplus
+
+typedef void (*poke32_func)(const uint32_t addr, const uint32_t data);
+typedef uint32_t (*peek32_func)(const uint32_t addr);
+
+/*!
+ * Process a firmware communication packet and compute a response.
+ * Args:
+ * - (in) request: Pointer to the request struct
+ * - (out) response: Pointer to the response struct
+ * - (in) product_id: The 8-bit usrp3 specific product ID (for request filtering)
+ * - (func) poke_callback, peek_callback: Callback functions for a single peek/poke
+ * - return value: Send a response packet
+ */
+bool process_fw_comm_protocol_pkt(
+ const fw_comm_pkt_t* request,
+ fw_comm_pkt_t* response,
+ uint8_t product_id,
+ uint32_t iface_id,
+ poke32_func poke_callback,
+ peek32_func peek_callback
+);
+
+#endif //ifdef __cplusplus
+
+#endif /* INCLUDED_FW_COMM_PROTOCOL */
diff --git a/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp b/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp
index d3f11b9ee..aefd84882 100644
--- a/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp
+++ b/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp
@@ -17,13 +17,13 @@
#include "usrp3_fw_ctrl_iface.hpp"
-#include "../../../firmware/usrp3/include/fw_comm_protocol.h"
#include <uhd/utils/byteswap.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/exception.hpp>
#include <boost/format.hpp>
#include <boost/asio.hpp> //used for htonl and ntohl
#include <boost/foreach.hpp>
+#include "fw_comm_protocol.h"
namespace uhd { namespace usrp { namespace usrp3 {
diff --git a/host/lib/usrp/n230/n230_cores.cpp b/host/lib/usrp/n230/n230_cores.cpp
index 14e99b692..58c702ec1 100644
--- a/host/lib/usrp/n230/n230_cores.cpp
+++ b/host/lib/usrp/n230/n230_cores.cpp
@@ -15,9 +15,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include "../../../firmware/usrp3/n230/n230_fw_defs.h"
#include "n230_cores.hpp"
#include "n230_fpga_defs.h"
+#include "n230_fw_defs.h"
namespace uhd { namespace usrp { namespace n230 {
diff --git a/host/lib/usrp/n230/n230_eeprom_manager.cpp b/host/lib/usrp/n230/n230_eeprom_manager.cpp
index ed40b47be..40f501ef9 100644
--- a/host/lib/usrp/n230/n230_eeprom_manager.cpp
+++ b/host/lib/usrp/n230/n230_eeprom_manager.cpp
@@ -65,10 +65,22 @@ const mboard_eeprom_t& n230_eeprom_manager::read_mb_eeprom()
const n230_eeprom_map_t* map_ptr = reinterpret_cast<const n230_eeprom_map_t*>(_response.data);
const n230_eeprom_map_t& map = *map_ptr;
+ uint16_t ver_major = uhd::htonx<boost::uint16_t>(map.data_version_major);
+ uint16_t ver_minor = uhd::htonx<boost::uint16_t>(map.data_version_minor);
+
_mb_eeprom["product"] = boost::lexical_cast<std::string>(
uhd::htonx<boost::uint16_t>(map.hw_product));
_mb_eeprom["revision"] = boost::lexical_cast<std::string>(
uhd::htonx<boost::uint16_t>(map.hw_revision));
+ //The revision_compat field does not exist in version 1.0
+ //EEPROM version 1.0 will only exist on HW revision 1 so it is safe to set
+ //revision_compat = revision
+ if (ver_major == 1 and ver_minor == 0) {
+ _mb_eeprom["revision_compat"] = _mb_eeprom["revision"];
+ } else {
+ _mb_eeprom["revision_compat"] = boost::lexical_cast<std::string>(
+ uhd::htonx<boost::uint16_t>(map.hw_revision_compat));
+ }
_mb_eeprom["serial"] = _bytes_to_string(
map.serial, N230_EEPROM_SERIAL_LEN);
@@ -104,6 +116,15 @@ void n230_eeprom_manager::write_mb_eeprom(const mboard_eeprom_t& eeprom)
memcpy(map_ptr, _response.data, sizeof(n230_eeprom_map_t));
n230_eeprom_map_t& map = *map_ptr;
+ // Automatic version upgrade handling
+ uint16_t old_ver_major = uhd::htonx<boost::uint16_t>(map.data_version_major);
+ uint16_t old_ver_minor = uhd::htonx<boost::uint16_t>(map.data_version_minor);
+
+ //The revision_compat field does not exist for version 1.0 so force write it
+ //EEPROM version 1.0 will only exist on HW revision 1 so it is safe to set
+ //revision_compat = revision for the upgrade
+ bool force_write_version_compat = (old_ver_major == 1 and old_ver_minor == 0);
+
map.data_version_major = uhd::htonx<boost::uint16_t>(N230_EEPROM_VER_MAJOR);
map.data_version_minor = uhd::htonx<boost::uint16_t>(N230_EEPROM_VER_MINOR);
@@ -115,6 +136,12 @@ void n230_eeprom_manager::write_mb_eeprom(const mboard_eeprom_t& eeprom)
map.hw_revision = uhd::htonx<boost::uint16_t>(
boost::lexical_cast<boost::uint16_t>(_mb_eeprom["revision"]));
}
+ if (_mb_eeprom.has_key("revision_compat")) {
+ map.hw_revision_compat = uhd::htonx<boost::uint16_t>(
+ boost::lexical_cast<boost::uint16_t>(_mb_eeprom["revision_compat"]));
+ } else if (force_write_version_compat) {
+ map.hw_revision_compat = map.hw_revision;
+ }
if (_mb_eeprom.has_key("serial")) {
_string_to_bytes(_mb_eeprom["serial"], N230_EEPROM_SERIAL_LEN, map.serial);
}
diff --git a/host/lib/usrp/n230/n230_eeprom_manager.hpp b/host/lib/usrp/n230/n230_eeprom_manager.hpp
index 612124d89..cc5aee9f3 100644
--- a/host/lib/usrp/n230/n230_eeprom_manager.hpp
+++ b/host/lib/usrp/n230/n230_eeprom_manager.hpp
@@ -18,11 +18,11 @@
#ifndef INCLUDED_N230_EEPROM_MANAGER_HPP
#define INCLUDED_N230_EEPROM_MANAGER_HPP
-#include "../../../firmware/usrp3/n230/n230_fw_host_iface.h"
#include <boost/thread/mutex.hpp>
#include <uhd/transport/udp_simple.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
+#include "n230_fw_host_iface.h"
namespace uhd { namespace usrp { namespace n230 {
diff --git a/host/lib/usrp/n230/n230_fw_defs.h b/host/lib/usrp/n230/n230_fw_defs.h
new file mode 100644
index 000000000..fbdc67ebb
--- /dev/null
+++ b/host/lib/usrp/n230/n230_fw_defs.h
@@ -0,0 +1,137 @@
+//
+// Copyright 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_N230_FW_DEFS_H
+#define INCLUDED_N230_FW_DEFS_H
+
+#include <stdint.h>
+
+/*!
+ * Constants specific to N230 firmware.
+ * This header is shared by the firmware and host code.
+ * Therefore, this header may only contain valid C code.
+ * However, if it is included from within the host code,
+ * it will be namespaced appropriately
+ */
+#ifdef __cplusplus
+namespace uhd {
+namespace usrp {
+namespace n230 {
+namespace fw {
+#endif
+
+static inline uint32_t reg_addr(uint32_t base, uint32_t offset) {
+ return ((base) + (offset)*4);
+}
+
+/*******************************************************************
+ * Global
+ *******************************************************************/
+static const uint32_t CPU_CLOCK_FREQ = 80000000;
+static const uint32_t PER_MILLISEC_CRON_JOBID = 0;
+static const uint32_t PER_SECOND_CRON_JOBID = 1;
+
+/*******************************************************************
+ * Wishbone slave addresses
+ *******************************************************************/
+static const uint32_t WB_MAIN_RAM_BASE = 0x0000;
+static const uint32_t WB_PKT_RAM_BASE = 0x8000;
+static const uint32_t WB_SBRB_BASE = 0xa000;
+static const uint32_t WB_SPI_FLASH_BASE = 0xb000;
+static const uint32_t WB_ETH0_MAC_BASE = 0xc000;
+static const uint32_t WB_ETH1_MAC_BASE = 0xd000;
+static const uint32_t WB_XB_SBRB_BASE = 0xe000;
+static const uint32_t WB_ETH0_I2C_BASE = 0xf600;
+static const uint32_t WB_ETH1_I2C_BASE = 0xf700;
+static const uint32_t WB_DBG_UART_BASE = 0xf900;
+
+/*******************************************************************
+ * Seting Register Base addresses
+ *******************************************************************/
+static const uint32_t SR_ZPU_SW_RST = 0;
+static const uint32_t SR_ZPU_BOOT_DONE = 1;
+static const uint32_t SR_ZPU_LEDS = 2;
+static const uint32_t SR_ZPU_XB_LOCAL = 4;
+static const uint32_t SR_ZPU_SFP_CTRL0 = 16;
+static const uint32_t SR_ZPU_SFP_CTRL1 = 17;
+static const uint32_t SR_ZPU_ETHINT0 = 64;
+static const uint32_t SR_ZPU_ETHINT1 = 80;
+
+static const uint32_t SR_ZPU_SW_RST_NONE = 0x0;
+static const uint32_t SR_ZPU_SW_RST_PHY = 0x1;
+static const uint32_t SR_ZPU_SW_RST_RADIO = 0x2;
+
+/*******************************************************************
+ * Readback addresses
+ *******************************************************************/
+static const uint32_t RB_ZPU_COMPAT = 0;
+static const uint32_t RB_ZPU_COUNTER = 1;
+static const uint32_t RB_ZPU_SFP_STATUS0 = 2;
+static const uint32_t RB_ZPU_SFP_STATUS1 = 3;
+static const uint32_t RB_ZPU_ETH0_PKT_CNT = 6;
+static const uint32_t RB_ZPU_ETH1_PKT_CNT = 7;
+
+/*******************************************************************
+ * Ethernet
+ *******************************************************************/
+static const uint32_t WB_PKT_RAM_CTRL_OFFSET = 0x1FFC;
+
+static const uint32_t SR_ZPU_ETHINT_FRAMER_BASE = 0;
+static const uint32_t SR_ZPU_ETHINT_DISPATCHER_BASE = 8;
+
+//Eth framer constants
+static const uint32_t ETH_FRAMER_SRC_MAC_HI = 0;
+static const uint32_t ETH_FRAMER_SRC_MAC_LO = 1;
+static const uint32_t ETH_FRAMER_SRC_IP_ADDR = 2;
+static const uint32_t ETH_FRAMER_SRC_UDP_PORT = 3;
+static const uint32_t ETH_FRAMER_DST_RAM_ADDR = 4;
+static const uint32_t ETH_FRAMER_DST_IP_ADDR = 5;
+static const uint32_t ETH_FRAMER_DST_UDP_MAC = 6;
+static const uint32_t ETH_FRAMER_DST_MAC_LO = 7;
+
+/*******************************************************************
+ * CODEC
+ *******************************************************************/
+static const uint32_t CODEC_SPI_CLOCK_FREQ = 4000000; //4MHz
+static const uint32_t ADF4001_SPI_CLOCK_FREQ = 200000; //200kHz
+
+/*******************************************************************
+ * UART
+ *******************************************************************/
+static const uint32_t DBG_UART_BAUD = 115200;
+
+/*******************************************************************
+ * Build Compatability Numbers
+ *******************************************************************/
+static const uint8_t PRODUCT_NUM = 0x01;
+static const uint8_t COMPAT_MAJOR = 0x00;
+static const uint16_t COMPAT_MINOR = 0x0000;
+
+static inline uint8_t get_prod_num(uint32_t compat_reg) {
+ return (compat_reg >> 24) & 0xFF;
+}
+static inline uint8_t get_compat_major(uint32_t compat_reg) {
+ return (compat_reg >> 16) & 0xFF;
+}
+static inline uint8_t get_compat_minor(uint32_t compat_reg) {
+ return compat_reg & 0xFFFF;
+}
+
+#ifdef __cplusplus
+}}}} //namespace
+#endif
+#endif /* INCLUDED_N230_FW_DEFS_H */
diff --git a/host/lib/usrp/n230/n230_fw_host_iface.h b/host/lib/usrp/n230/n230_fw_host_iface.h
new file mode 100644
index 000000000..dc82df2fc
--- /dev/null
+++ b/host/lib/usrp/n230/n230_fw_host_iface.h
@@ -0,0 +1,128 @@
+//
+// Copyright 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_N230_FW_HOST_IFACE_H
+#define INCLUDED_N230_FW_HOST_IFACE_H
+
+#include <stdint.h>
+
+/*!
+ * Structs and constants for N230 communication between firmware and host.
+ * This header is shared by the firmware and host code.
+ * Therefore, this header may only contain valid C code.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------
+// Ethernet related
+//
+#define N230_DEFAULT_ETH0_MAC {0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff}
+#define N230_DEFAULT_ETH1_MAC {0x00, 0x50, 0xC2, 0x85, 0x3f, 0x33}
+#define N230_DEFAULT_ETH0_IP (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0)
+#define N230_DEFAULT_ETH1_IP (192 << 24 | 168 << 16 | 20 << 8 | 2 << 0)
+#define N230_DEFAULT_ETH0_MASK (255 << 24 | 255 << 16 | 255 << 8 | 0 << 0)
+#define N230_DEFAULT_ETH1_MASK (255 << 24 | 255 << 16 | 255 << 8 | 0 << 0)
+#define N230_DEFAULT_GATEWAY (192 << 24 | 168 << 16 | 10 << 8 | 1 << 0)
+
+#define N230_FW_COMMS_UDP_PORT 49152
+#define N230_FW_COMMS_CVITA_PORT 49153
+#define N230_FW_COMMS_FLASH_PROG_PORT 49154
+//
+//--------------------------------------------------
+
+//--------------------------------------------------
+// Memory shared with host
+//
+#define N230_FW_HOST_SHMEM_BASE_ADDR 0x10000
+#define N230_FW_HOST_SHMEM_RW_BASE_ADDR 0x1000C
+#define N230_FW_HOST_SHMEM_NUM_WORDS (sizeof(n230_host_shared_mem_data_t)/sizeof(uint32_t))
+
+#define N230_FW_HOST_SHMEM_MAX_ADDR \
+ (N230_FW_HOST_SHMEM_BASE_ADDR + ((N230_FW_HOST_SHMEM_NUM_WORDS - 1) * sizeof(uint32_t)))
+
+#define N230_FW_HOST_SHMEM_OFFSET(member) \
+ (N230_FW_HOST_SHMEM_BASE_ADDR + ((uint32_t)offsetof(n230_host_shared_mem_data_t, member)))
+
+//The shared memory block can only be accessed on 32-bit boundaries
+typedef struct { //All fields must be 32-bit wide to avoid packing directives
+ //Read-Only fields (N230_FW_HOST_SHMEM_BASE_ADDR)
+ uint32_t fw_compat_num; //Compat number must be at offset 0
+ uint32_t fw_version_hash;
+ uint32_t claim_status;
+
+ //Read-Write fields (N230_FW_HOST_SHMEM_RW_BASE_ADDR)
+ uint32_t scratch;
+ uint32_t claim_time;
+ uint32_t claim_src;
+} n230_host_shared_mem_data_t;
+
+typedef union
+{
+ uint32_t buff[N230_FW_HOST_SHMEM_NUM_WORDS];
+ n230_host_shared_mem_data_t data;
+} n230_host_shared_mem_t;
+
+#define N230_FW_PRODUCT_ID 1
+#define N230_FW_COMPAT_NUM_MAJOR 3
+#define N230_FW_COMPAT_NUM_MINOR 0
+#define N230_FW_COMPAT_NUM (((N230_FW_COMPAT_NUM_MAJOR & 0xFF) << 16) | (N230_FW_COMPAT_NUM_MINOR & 0xFFFF))
+//
+//--------------------------------------------------
+
+//--------------------------------------------------
+// Flash read-write interface for host
+//
+#define N230_FLASH_COMM_FLAGS_ACK 0x00000001
+#define N230_FLASH_COMM_FLAGS_CMD_MASK 0x00000FF0
+#define N230_FLASH_COMM_FLAGS_ERROR_MASK 0xFF000000
+
+#define N230_FLASH_COMM_CMD_READ_NV_DATA 0x00000010
+#define N230_FLASH_COMM_CMD_WRITE_NV_DATA 0x00000020
+#define N230_FLASH_COMM_CMD_READ_FPGA 0x00000030
+#define N230_FLASH_COMM_CMD_WRITE_FPGA 0x00000040
+#define N230_FLASH_COMM_CMD_ERASE_FPGA 0x00000050
+
+#define N230_FLASH_COMM_ERR_PKT_ERROR 0x80000000
+#define N230_FLASH_COMM_ERR_CMD_ERROR 0x40000000
+#define N230_FLASH_COMM_ERR_SIZE_ERROR 0x20000000
+
+#define N230_FLASH_COMM_MAX_PAYLOAD_SIZE 128
+
+typedef struct
+{
+ uint32_t flags;
+ uint32_t seq;
+ uint32_t offset;
+ uint32_t size;
+ uint8_t data[N230_FLASH_COMM_MAX_PAYLOAD_SIZE];
+} n230_flash_prog_t;
+//
+//--------------------------------------------------
+
+#define N230_HW_REVISION_COMPAT 1
+#define N230_HW_REVISION_MIN 1
+
+
+#define N230_CLAIMER_TIMEOUT_IN_MS 2000
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_N230_FW_HOST_IFACE_H */
diff --git a/host/lib/usrp/n230/n230_image_loader.cpp b/host/lib/usrp/n230/n230_image_loader.cpp
index 48b41c7a9..f8a6ba092 100644
--- a/host/lib/usrp/n230/n230_image_loader.cpp
+++ b/host/lib/usrp/n230/n230_image_loader.cpp
@@ -24,8 +24,9 @@
#include <uhd/transport/udp_simple.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
+
+#include "n230_fw_host_iface.h"
#include "n230_impl.hpp"
-#include "../../../firmware/usrp3/n230/n230_fw_host_iface.h"
using namespace uhd;
using namespace uhd::usrp;
diff --git a/host/lib/usrp/n230/n230_impl.cpp b/host/lib/usrp/n230/n230_impl.cpp
index b3cc4ab59..ab7fa6fe6 100644
--- a/host/lib/usrp/n230/n230_impl.cpp
+++ b/host/lib/usrp/n230/n230_impl.cpp
@@ -17,9 +17,6 @@
#include "n230_impl.hpp"
-#include "../../../firmware/usrp3/n230/n230_fw_host_iface.h"
-#include "../../../firmware/usrp3/n230/n230_fw_defs.h"
-#include "../../../firmware/usrp3/include/fw_comm_protocol.h"
#include "usrp3_fw_ctrl_iface.hpp"
#include "validate_subdev_spec.hpp"
#include <uhd/utils/static.hpp>
@@ -31,6 +28,7 @@
#include <uhd/utils/msg.hpp>
#include <uhd/types/sensors.hpp>
#include <uhd/types/ranges.hpp>
+#include <uhd/types/direction.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
#include <uhd/usrp/dboard_eeprom.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
@@ -43,8 +41,12 @@
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio.hpp> //used for htonl and ntohl
#include <boost/make_shared.hpp>
+
+#include "../common/fw_comm_protocol.h"
#include "n230_defaults.h"
#include "n230_fpga_defs.h"
+#include "n230_fw_defs.h"
+#include "n230_fw_host_iface.h"
namespace uhd { namespace usrp { namespace n230 {
@@ -180,13 +182,37 @@ n230_impl::n230_impl(const uhd::device_addr_t& dev_addr)
//TODO: Only supports one motherboard per device class.
const fs_path mb_path = "/mboards/0";
- //Initialize subsystems
+ //Initialize addresses
std::vector<std::string> ip_addrs(1, dev_addr["addr"]);
if (dev_addr.has_key("secondary-addr")) {
ip_addrs.push_back(dev_addr["secondary-addr"]);
}
- _resource_mgr = boost::make_shared<n230_resource_manager>(ip_addrs, _dev_args.get_safe_mode());
+
+ //Read EEPROM and perform version checks before talking to HW
_eeprom_mgr = boost::make_shared<n230_eeprom_manager>(ip_addrs[0]);
+ const mboard_eeprom_t& mb_eeprom = _eeprom_mgr->get_mb_eeprom();
+ bool recover_mb_eeprom = dev_addr.has_key("recover_mb_eeprom");
+ if (recover_mb_eeprom) {
+ UHD_MSG(warning) << "UHD is operating in EEPROM Recovery Mode which disables hardware version "
+ "checks.\nOperating in this mode may cause hardware damage and unstable "
+ "radio performance!"<< std::endl;
+ }
+ boost::uint16_t hw_rev = boost::lexical_cast<boost::uint16_t>(mb_eeprom["revision"]);
+ boost::uint16_t hw_rev_compat = boost::lexical_cast<boost::uint16_t>(mb_eeprom["revision_compat"]);
+ if (not recover_mb_eeprom) {
+ if (hw_rev_compat > N230_HW_REVISION_COMPAT) {
+ throw uhd::runtime_error(str(boost::format(
+ "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.")
+ % hw_rev));
+ } else if (hw_rev < N230_HW_REVISION_MIN) { //Compare min against the revision (and not compat) to give us more leeway for partial support for a compat
+ throw uhd::runtime_error(str(boost::format(
+ "Software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.")
+ % hw_rev));
+ }
+ }
+
+ //Initialize all subsystems
+ _resource_mgr = boost::make_shared<n230_resource_manager>(ip_addrs, _dev_args.get_safe_mode());
_stream_mgr = boost::make_shared<n230_stream_manager>(_dev_args, _resource_mgr, _tree);
//Build property tree
@@ -459,38 +485,14 @@ void n230_impl::_initialize_radio_properties(const fs_path& mb_path, size_t inst
.publish(boost::bind(&tx_dsp_core_3000::get_freq_range, perif.duc));
//RF Frontend Interfacing
- static const std::vector<std::string> data_directions = boost::assign::list_of("tx")("rx");
- BOOST_FOREACH(const std::string& direction, data_directions) {
- const std::string key = boost::to_upper_copy(direction) + str(boost::format("%u") % (instance + 1));
- const fs_path rf_fe_path = mb_path / "dboards" / "A" / (direction + "_frontends") / ((instance==0)?"A":"B");
-
- _tree->create<std::string>(rf_fe_path / "name")
- .set("FE-" + key);
- _tree->create<int>(rf_fe_path / "sensors"); //empty TODO
- BOOST_FOREACH(const std::string &name, ad9361_ctrl::get_gain_names(key)) {
- _tree->create<meta_range_t>(rf_fe_path / "gains" / name / "range")
- .set(ad9361_ctrl::get_gain_range(key));
- _tree->create<double>(rf_fe_path / "gains" / name / "value")
- .coerce(boost::bind(&ad9361_ctrl::set_gain, _resource_mgr->get_codec_ctrl_sptr(), key, _1))
- .set(n230::DEFAULT_FE_GAIN);
- }
- _tree->create<std::string>(rf_fe_path / "connection")
- .set("IQ");
- _tree->create<bool>(rf_fe_path / "enabled")
- .set(true);
- _tree->create<bool>(rf_fe_path / "use_lo_offset")
- .set(false);
- _tree->create<double>(rf_fe_path / "bandwidth" / "value")
- .coerce(boost::bind(&ad9361_ctrl::set_bw_filter, _resource_mgr->get_codec_ctrl_sptr(), key, _1))
- .set(n230::DEFAULT_FE_BW);
- _tree->create<meta_range_t>(rf_fe_path / "bandwidth" / "range")
- .publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key));
- _tree->create<double>(rf_fe_path / "freq" / "value")
- .set(n230::DEFAULT_FE_FREQ)
- .coerce(boost::bind(&ad9361_ctrl::tune, _resource_mgr->get_codec_ctrl_sptr(), key, _1))
- .subscribe(boost::bind(&n230_frontend_ctrl::set_bandsel, _resource_mgr->get_frontend_ctrl_sptr(), key, _1));
- _tree->create<meta_range_t>(rf_fe_path / "freq" / "range")
- .publish(boost::bind(&ad9361_ctrl::get_rf_freq_range));
+ static const std::vector<direction_t> data_directions = boost::assign::list_of(RX_DIRECTION)(TX_DIRECTION);
+ BOOST_FOREACH(direction_t direction, data_directions) {
+ const std::string dir_str = (direction == RX_DIRECTION) ? "rx" : "tx";
+ const std::string key = boost::to_upper_copy(dir_str) + str(boost::format("%u") % (instance + 1));
+ const fs_path rf_fe_path = mb_path / "dboards" / "A" / (dir_str + "_frontends") / ((instance==0)?"A":"B");
+
+ //CODEC subtree
+ _resource_mgr->get_codec_mgr().populate_frontend_subtree(_tree->subtree(rf_fe_path), key, direction);
//User settings
_tree->create<uhd::wb_iface::sptr>(rf_fe_path / "user_settings" / "iface")
diff --git a/host/lib/usrp/n230/n230_resource_manager.cpp b/host/lib/usrp/n230/n230_resource_manager.cpp
index 38e689533..4db494302 100644
--- a/host/lib/usrp/n230/n230_resource_manager.cpp
+++ b/host/lib/usrp/n230/n230_resource_manager.cpp
@@ -17,8 +17,6 @@
#include "n230_resource_manager.hpp"
-#include "../../../firmware/usrp3/n230/n230_fw_host_iface.h"
-#include "../../../firmware/usrp3/n230/n230_fw_defs.h"
#include "usrp3_fw_ctrl_iface.hpp"
#include <uhd/transport/if_addrs.hpp>
#include <uhd/transport/udp_zero_copy.hpp>
@@ -32,6 +30,8 @@
#include <boost/functional/hash.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
+#include "n230_fw_defs.h"
+#include "n230_fw_host_iface.h"
#define IF_DATA_I_MASK 0xFFF00000
#define IF_DATA_Q_MASK 0x0000FFF0
@@ -88,12 +88,19 @@ n230_resource_manager::n230_resource_manager(
n230_eth_conn_t conn_iface;
conn_iface.ip_addr = addr;
- boost::uint32_t iface_id = usrp3::usrp3_fw_ctrl_iface::get_iface_id(
- conn_iface.ip_addr, BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT), N230_FW_PRODUCT_ID);
+ boost::uint32_t iface_id = 0xFFFFFFFF;
+ try {
+ iface_id = usrp3::usrp3_fw_ctrl_iface::get_iface_id(
+ conn_iface.ip_addr, BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT), N230_FW_PRODUCT_ID);
+ } catch (uhd::io_error&) {
+ throw uhd::io_error(str(boost::format(
+ "Could not communicate with the device over address %s") %
+ conn_iface.ip_addr));
+ }
switch (iface_id) {
case N230_ETH0_IFACE_ID: conn_iface.type = ETH0; break;
case N230_ETH1_IFACE_ID: conn_iface.type = ETH1; break;
- default: throw uhd::runtime_error("N230 Initialization Error: Could not detect iface.)");
+ default: throw uhd::runtime_error("N230 Initialization Error: Could not detect ethernet port number.)");
}
_eth_conns.push_back(conn_iface);
}
@@ -143,7 +150,7 @@ n230_resource_manager::n230_resource_manager(
throw uhd::runtime_error("N230 Initialization Error: Could not create SPI ctrl.)");
}
- //Create Catalina interface
+ //Create AD9361 interface
UHD_MSG(status) << "Initializing CODEC...\n";
_codec_ctrl = ad9361_ctrl::make_spi(
boost::make_shared<n230_ad9361_client_t>(), _core_spi_ctrl, fpga::AD9361_SPI_SLAVE_NUM);
@@ -151,6 +158,8 @@ n230_resource_manager::n230_resource_manager(
throw uhd::runtime_error("N230 Initialization Error: Could not create Catalina ctrl.)");
}
_codec_ctrl->set_clock_rate(fpga::CODEC_DEFAULT_CLK_RATE);
+ _codec_mgr = ad936x_manager::make(_codec_ctrl, fpga::NUM_RADIOS);
+ _codec_mgr->init_codec();
//Create AD4001 interface
_ref_pll_ctrl = boost::make_shared<n230_ref_pll_ctrl>(_core_spi_ctrl);
diff --git a/host/lib/usrp/n230/n230_resource_manager.hpp b/host/lib/usrp/n230/n230_resource_manager.hpp
index c98140141..3a0b13329 100644
--- a/host/lib/usrp/n230/n230_resource_manager.hpp
+++ b/host/lib/usrp/n230/n230_resource_manager.hpp
@@ -28,6 +28,7 @@
#include "tx_dsp_core_3000.hpp"
#include "user_settings_core_3000.hpp"
#include "ad9361_ctrl.hpp"
+#include "ad936x_manager.hpp"
#include <uhd/utils/tasks.hpp>
#include <uhd/types/sid.hpp>
#include <uhd/types/device_addr.hpp>
@@ -139,13 +140,16 @@ public: //Methods
return _core_ctrl;
}
- //Catalina control interface
+ //AD931 control interface
inline ad9361_ctrl& get_codec_ctrl() const {
return *_codec_ctrl;
}
inline ad9361_ctrl::sptr get_codec_ctrl_sptr() {
return _codec_ctrl;
}
+ inline uhd::usrp::ad936x_manager& get_codec_mgr() const {
+ return *_codec_mgr;
+ }
//Clock PPS controls
inline n230_ref_pll_ctrl& get_ref_pll_ctrl() const {
@@ -282,6 +286,7 @@ private:
radio_ctrl_core_3000::sptr _core_ctrl;
n230_core_spi_core::sptr _core_spi_ctrl;
ad9361_ctrl::sptr _codec_ctrl;
+ uhd::usrp::ad936x_manager::sptr _codec_mgr;
//Core Registers
fpga::core_radio_ctrl_reg_t _core_radio_ctrl_reg;