mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
It is, in principle, possible to use an external clock to synchronize N3x0 devices in frequency, and then use a GPSDO for a coarse time synchronization. This use case is deliberately not supported, as the GPSDO PPS signal and the external clock signal are by definition not matched, which will remove any guarantees on time/phase alignment. Because there are certain, niche use cases where the lack of phase alignment is acceptable, but only an external clock is available (no shared external PPS), usage of GPS for generating a PPS signal may be fine. This patch does not enable the usage of this combination out of the box, but adds comments and an update to the manual to explain the risks of this combination, and how to enable it (by patching MPM).
1725 lines
88 KiB
Plaintext
1725 lines
88 KiB
Plaintext
/*! \page page_usrp_n3xx USRP N3xx Series
|
||
|
||
\tableofcontents
|
||
|
||
\section n3xx_feature_list Comparative features list
|
||
|
||
- Hardware Capabilities:
|
||
- Dual SFP+ Transceivers (can be used with 1 GigE, 10 GigE, and Aurora)
|
||
- External PPS input & output
|
||
- External 10 MHz input & output (20 MHz and 25 MHz inputs also supported)
|
||
- External White Rabbit time/frequency reference input support
|
||
- Internal 25 MHz reference clock
|
||
- Internal GPSDO for timing, location, and 20 MHz reference clock + PPS
|
||
- External GPIO Connector with UHD API control
|
||
- External USB Connection for built-in JTAG debugger and serial console
|
||
- Xilinx Zynq SoC with dual-core ARM Cortex A9 (Speedgrade 2) and
|
||
Kintex-7 FPGA (XC7Z100 or XC7Z035 depending on variant)
|
||
|
||
- Software Capabilities:
|
||
- Full Linux system running on the ARM core
|
||
- Runs MPM (see also \ref page_mpm)
|
||
|
||
- FPGA Capabilities:
|
||
- Timed commands in FPGA
|
||
- Timed sampling in FPGA
|
||
- RFNoC capability
|
||
|
||
The N3XX series of USRPs is designed as a platform. The following USRPs are
|
||
variants of the N3XX series:
|
||
|
||
\subsection n3xx_feature_list_mg N310/N300 4-channel/2-channel Transceiver
|
||
|
||
\image html N310isoExplode.png N310 Exploded View
|
||
|
||
- Supported master clock rates: 122.88 MHz, 125 MHz, 153.6 MHz
|
||
- Tuning range: 10 MHz to 6 GHz
|
||
- Below 300 MHz, additional LOs and mixer stages
|
||
are used to shift the signal into the frequency range of the AD9371
|
||
- Tunable down to 1 MHz in UHD however performance is not guaranteed
|
||
- Support for external LOs
|
||
- 4 RX DDC chains in FPGA (2 for N300)
|
||
- 4 TX DUC chain in FPGA (2 for N300)
|
||
- 2 SFP+ connectors
|
||
|
||
The N310 is a 4-channel transmitter/receiver based on the AD9371 transceiver IC.
|
||
It has two daughterboards with one AD9371 each; every daughterboard provides
|
||
two RF channels. Note that the product code "N310" refers to the module
|
||
consisting of mother- and daughterboard, the daughterboard itself is referred to
|
||
by its codename, "Magnesium".
|
||
|
||
The N300 is a subset of the N310. It has 2 TX/RX channels (on a single
|
||
daughterboard; the daughterboard itself is the same as the N310) and a smaller
|
||
FPGA (XCZ035). Also, it does not have connectors for external LOs.
|
||
|
||
\subsection n3xx_feature_list_rh N320/N321 2-channel Transceiver
|
||
|
||
- Supported master clock rates: 200 MHz, 245.76 MHz, 250 MHz
|
||
- Tuning range: 3 MHz to 6 GHz
|
||
- Below 450 MHz, an additional LO and mixer stage
|
||
is used to shift the signal into the range of the main LO stage
|
||
- Tunable down to 1 MHz in UHD however performance is not guaranteed
|
||
- Support for external LOs
|
||
- 2 RX DDC chains in FPGA
|
||
- 2 TX DUC chain in FPGA
|
||
- LO sharing between multiple devices (N321 only)
|
||
- 2 SFP+ connectors + 1 QSFP+ connector
|
||
|
||
The N320 is a 2-channel transmitter/receiver using discrete components instead
|
||
of an RFIC. It has two daughterboards, each has one ADC/DAC and provides one
|
||
RF channel.
|
||
|
||
The difference between the N320 and the N321 is in its LO sharing capability.
|
||
The N320 has a single input for the TX and RX LOs, respectively. The N321 also
|
||
has the ability to export its LO up to four times, making it possible to share
|
||
LOs between a large number of N321 devices without having to provide an
|
||
external, separate LO source. Due to number of connectors required to provide
|
||
the large number of LO outputs, the N321 does not have a front-panel GPIO
|
||
connector.
|
||
|
||
The N320 has a higher maximum analog bandwidth than the N310. It can provide
|
||
rates up to 250 Msps, resulting in a usable analog bandwidth of up to 200 MHz.
|
||
In order to better use the high available rates, the N320/N321 devices have an
|
||
additional QSFP+ connector on the back panel which can be used for streaming
|
||
data to and from the radios. In order to facilitate the higher bandwidth, UHD
|
||
uses a technology called \ref page_dpdk "Data Plane Development Kit (DPDK)".
|
||
See the DPDK page for details on how it can improve streaming, and how to use
|
||
it.
|
||
|
||
\section n3xx_overview Overview
|
||
|
||
\subsection n3xx_zynq The Zynq CPU/FPGA and host operating system
|
||
|
||
The main CPU of the N310 is a Xilinx Zynq SoC XC7Z100 (exception: The N300). It
|
||
is both a dual-core ARM Cortex A9 CPU and Kintex-7 FPGA on a single die. The
|
||
CPU is clocked at 800 MHz (speedgrade 2).
|
||
|
||
The programmable logic (PL, or FPGA) section of the SoC is responsible for
|
||
handling all sampling data, the 10 GigE network connections, and any other
|
||
high-speed utility such as custom RFNoC logic. The processing system (PS, or CPU)
|
||
is running a custom-build OpenEmbedded-based Linux operating system. The OS is
|
||
responsible for all the device and peripheral management, such as running MPM,
|
||
configuring the network interfaces, running local UHD sessions, etc.
|
||
|
||
It is possible to connect to the host OS either via SSH or serial console (see
|
||
sections \ref n3xx_getting_started_ssh and \ref n3xx_getting_started_serial,
|
||
respectively).
|
||
|
||
\subsection n3xx_micro The STM32 microcontroller
|
||
|
||
The STM32 microcontroller controls various low-level features of the N3xx series
|
||
motherboard: It controls the power sequencing, reads out fan speeds and some of
|
||
the temperature sensors. It is connected to the Zynq via an I2C bus.
|
||
|
||
It is possible to log into the STM32 using the serial interface
|
||
(see \ref n3xx_getting_started_serial_micro). This will allow certain low-level
|
||
controls, such as remote power cycling should the CPU have become unresponsive
|
||
for whatever reason.
|
||
|
||
\subsection n3xx_sdcard The SD card
|
||
|
||
The N3XX series uses a micro SD card as its main storage. The entire root file
|
||
system (Linux kernel, libraries) and any user data are stored on this SD card.
|
||
|
||
The SD card is partitioned into four partitions:
|
||
|
||
1. Boot partition (contains the bootloader). This partition usually does not
|
||
require touching.
|
||
2. A data partition, mounted in /data. This is the only partition that is not
|
||
erased during file system updates.
|
||
2. Two identical system partitions (root file systems). These contain the
|
||
operating system and the home directory (anything mounted under / that is not
|
||
the data or boot partition). The reason there are two of these is to enable
|
||
remote updates: An update running on one partition can update the other one
|
||
without any effect to the currently running system. Note that the system
|
||
partitions are erased during updates and are thus unsuitable for permanently
|
||
storing information.
|
||
|
||
Note: It is possible to access the currently inactive root file system by
|
||
mounting it. After logging into the device using serial console or SSH (see the
|
||
following two sections), run the following commands:
|
||
|
||
$ mkdir temp
|
||
$ mount /dev/mmcblk0p3 temp
|
||
$ ls temp # You are now accessing the idle partition:
|
||
bin data etc lib media proc sbin tmp usr
|
||
boot dev home lost+found mnt run sys uboot var
|
||
|
||
The device node in the mount command will likely differ, depending on which
|
||
partition is currently already mounted.
|
||
|
||
\section n3xx_getting_started Getting started
|
||
|
||
This will run you through the first steps relevant to getting your USRP N3XX
|
||
series up and running.
|
||
|
||
\subsection n3xx_getting_started_assembling Assembling the N3XX
|
||
|
||
Unlike the X300 or N200 series, there is no assembly of daughterboards required.
|
||
Members of the N3XX product family, such as the N310, ship with daughterboards
|
||
pre-installed.
|
||
|
||
Checklist:
|
||
- Connect power and network
|
||
- Read security settings
|
||
- Connect clocking (if required)
|
||
- Connect external LOs (if required)
|
||
|
||
\subsection n3xx_getting_started_fs_update Updating the file system
|
||
|
||
Before doing any major work with a newly acquired USRP N300/N310, it is
|
||
recommended to update the file system. Updating the filesystem can be
|
||
accomplished directly on the N300/N310 by using Mender or externally by
|
||
manually writing an image onto a micro SD card and inserting it. While
|
||
manual updating is faster, Mender requires no direct physical access to the
|
||
device. For details on using Mender, see Section \ref n3xx_rasm_mender .
|
||
|
||
Manual updating is simply loading an image on the micro SD card. The first step
|
||
in that process is to obtain an image.
|
||
|
||
To obtain the default micro SD card image for a specific version of UHD, install
|
||
that version of UHD (3.11.0.1 or later) on a host system with Internet access and run:
|
||
|
||
$ uhd_images_downloader -t n3xx_common_sdimg_default
|
||
|
||
The image will be downloaded to
|
||
`<UHD_INSTALL_DIR>/share/uhd/images/usrp_n3xx_fs.sdimg`,
|
||
where `<UHD_INSTALL_DIR>` is the UHD installation directory.
|
||
|
||
To load an image onto the micro SD card, connect the card to the host and run:
|
||
|
||
$ sudo dd if=<YOUR_IMAGE> of=/dev/<YOUR_SD_CARD> bs=1M
|
||
|
||
The `<YOUR_IMAGE>` is the path to the micro SD card image
|
||
(i.e.`<UHD_INSTALL_DIR>/share/uhd/images/usrp_n3xx_fs.sdimg`).
|
||
|
||
The `<YOUR_SD_CARD>` device node depends on your operating system and which
|
||
other devices are plugged in. Typical values are `sdb` or `mmcblk0`.<br>
|
||
CAUTION: Operating on the wrong device can cause damage to that device.
|
||
|
||
The micro SD card used can be the original SD card shipped with the device or
|
||
another one that is at least 16 GB in size.
|
||
|
||
Insert the updated micro SD card and power on the device.
|
||
|
||
\subsection n3xx_getting_started_serial Serial connection
|
||
|
||
It is possible to gain root access to the device using a serial terminal
|
||
emulator. Most Linux, OSX, or other Unix flavours have a tool called 'screen'
|
||
which can be used for this purpose, by running the following command:
|
||
|
||
$ sudo screen /dev/ttyUSB2 115200
|
||
|
||
In this command, we prepend 'sudo' to elevate user privileges (by default,
|
||
accessing serial ports is not available to regular users), we specify the
|
||
device node (in this case, `/dev/ttyUSB2`), and the baud rate (115200).
|
||
|
||
The exact device node depends on your operating system's driver and other USB
|
||
devices that might be already connected. Modern Linux systems offer alternatives
|
||
to simply trying device nodes; instead, the OS might have a directory of
|
||
symlinks under `/dev/serial/by-id`:
|
||
|
||
$ ls /dev/serial/by-id
|
||
usb-Digilent_Digilent_USB_Device_25163511FE00-if00-port0
|
||
usb-Digilent_Digilent_USB_Device_25163511FE00-if01-port0
|
||
usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6CB5-if00-port0
|
||
usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6CB5-if01-port0
|
||
|
||
Note: Exact names depend on the host operating system version and may differ.
|
||
|
||
Every N3XX series device connected to USB will by default show up as four
|
||
different devices. The devices labeled "USB_to_UART_Bridge_Controller" are the
|
||
devices that offer a serial prompt. The first (with the `if00` suffix) connects
|
||
to Linux, whereas the second connects to the STM32 microcontroller.
|
||
If you have multiple N3XX devices connect, you may have to try out multiple
|
||
devices. In this case, to use this symlink instead of the raw device node
|
||
address, modify the command above to:
|
||
|
||
$ sudo screen /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6CB5-if00-port0 115200
|
||
|
||
You should be presented with a shell prompt similar to the following:
|
||
|
||
root@ni-n3xx-311FE00:~#
|
||
|
||
On this prompt, you can enter any Linux command available. Using the default
|
||
configuration, the serial console will also show all kernel log messages (unlike
|
||
when using SSH, for example), and give access to the boot loader (U-boot
|
||
prompt). This can be used to debug kernel or bootloader issues more efficiently
|
||
than when logged in via SSH.
|
||
|
||
\subsubsection n3xx_getting_started_serial_micro Connecting to the microcontroller
|
||
|
||
The STM32 microcontroller (which controls the power sequencing, among other
|
||
things) also has a serial console available. To connect to the microcontroller,
|
||
use the other UART device. In the example above:
|
||
|
||
$ sudo screen /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6CB5-if01-port0 115200
|
||
|
||
It provides a very simple prompt. The command 'help' will list all available
|
||
commands. A direct connection to the microcontroller can be used to hard-reset
|
||
the device without physically accessing it (i.e., emulating a power button press)
|
||
and other low-level diagnostics.
|
||
|
||
\subsection n3xx_getting_started_ssh SSH connection
|
||
|
||
The USRP N-Series devices have two network connections: The dual SFP ports,
|
||
and an RJ-45 connector. The latter is by default configured by DHCP; by plugging
|
||
it into into 1 Gigabit switch on a DHCP-capable network, it will get assigned
|
||
an IP address and thus be accessible via ssh.
|
||
|
||
In case your network setup does not include a DHCP server, refer to the section
|
||
\ref n3xx_getting_started_serial. A serial login can be used to assign an IP address manually.
|
||
|
||
After the device obtained an IP address you can log in from a Linux or OSX
|
||
machine by typing:
|
||
|
||
$ ssh root@ni-n3xx-311FE00 # Replace with your actual device name!
|
||
|
||
Depending on your network setup, using a `.local` domain may work:
|
||
|
||
$ ssh root@ni-n3xx-311FE00.local
|
||
|
||
Of course, you can also connect to the IP address directly if you know it (or
|
||
set it manually using the serial console).
|
||
|
||
Note: The device's hostname is derived from its serial number by default
|
||
(`ni-n3xx-$SERIAL`). You can change the hostname by creating the file
|
||
`/data/network/hostname`, saving the desired hostname in it, then rebooting.
|
||
|
||
On Microsoft Windows, the connection can be established using a tool such as
|
||
Putty, by selecting a username of root without password.
|
||
|
||
Like with the serial console, you should be presented with a prompt like the
|
||
following:
|
||
|
||
root@ni-n3xx-311FE00:~#
|
||
|
||
\subsection n3xx_getting_started_connectivity Network Connectivity
|
||
|
||
The RJ45 port (eth0) comes up with a default configuration of DHCP,
|
||
that will request a network address from your DHCP server (if available on your
|
||
network).
|
||
|
||
The SFP+ (sfp0, sfp1) ports are configured with static addresses 192.168.10.2/24
|
||
and 192.168.20.2/24, respectively. Their default MTU value is 9000. These
|
||
settings are independent of the image type (HG vs. XG), i.e., the defaults are
|
||
the same for 1 GigE and 10 GigE (unlike the X310!).
|
||
|
||
The configuration for the `sfpX` port is stored in `/data/network/sfpX.network`.
|
||
|
||
For configuration please refer to the
|
||
<a href=https://www.freedesktop.org/software/systemd/man/systemd.network.html>systemd-networkd manual pages</a>
|
||
|
||
The factory settings are as follows:
|
||
|
||
eth0 (DHCP):
|
||
|
||
[Match]
|
||
Name=eth0
|
||
|
||
[Network]
|
||
DHCP=v4
|
||
|
||
[DHCPv4]
|
||
UseHostname=false
|
||
|
||
sfp0 (static):
|
||
|
||
[Match]
|
||
Name=sfp0
|
||
|
||
[Network]
|
||
Address=192.168.10.2/24
|
||
|
||
[Link]
|
||
MTUBytes=9000
|
||
|
||
sfp1 (static):
|
||
|
||
[Match]
|
||
Name=sfp1
|
||
|
||
[Network]
|
||
Address=192.168.20.2/24
|
||
|
||
[Link]
|
||
MTUBytes=9000
|
||
|
||
|
||
Additional notes on networking:
|
||
|
||
- Care needs to be taken when editing these files on the device, since
|
||
vi / vim sometimes generates undo files (e.g.
|
||
`/data/network/sfp0.network~`), that systemd-networkd might
|
||
accidentally pick up.
|
||
- Temporarily setting the IP addresses or MTU sizes via `ifconfig` or other
|
||
command line tools will only change the value until the next reboot or reload
|
||
of the FPGA image.
|
||
- If the MTU of the device and host computers differ, streaming issues can
|
||
occur.
|
||
|
||
\subsection n3xx_getting_started_security Security-related settings
|
||
|
||
The N3XX ships without a root password set. It is possible to ssh into the
|
||
device by simply connecting as root, and thus gaining access to all subsystems.
|
||
To set a password, run the command
|
||
|
||
$ passwd
|
||
|
||
on the device.
|
||
|
||
\subsection n3xx_getting_started_fpga_update Updating the FPGA
|
||
|
||
Updating the FPGA follows the same procedure as other USRPs. Use the `uhd_image_loader`
|
||
command line utility to upload a new FPGA image onto the device.
|
||
|
||
A common reason to update the FPGA image is in the case of a UHD/FPGA compat
|
||
number mismatch (for example, if UHD has been updated, and now expects a newer
|
||
version of the FPGA than is on the device). In this case, simply run
|
||
|
||
$ uhd_images_downloader
|
||
|
||
to update the local cache of FPGA images. Then, run
|
||
|
||
$ uhd_image_loader --args type=n3xx,addr=ni-n3xx-311fe00
|
||
|
||
to update the FPGA using the default settings. If a custom FPGA image is targeted
|
||
for uploading, use the `--fpga-path` command line argument. Run
|
||
|
||
$ uhd_image_loader --help
|
||
|
||
to see a full list of command line options. Note that updating the FPGA image
|
||
will force a reload of the FPGA, which will temporarily take down the SFP
|
||
network interfaces (and temporary settings, such as applied via `ifconfig` on
|
||
the command line, will be lost).
|
||
|
||
\subsubsection n3xx_getting_started_fpga_update_flavors FPGA Image Flavors
|
||
|
||
The USRP-N300 Series devices contains two SFP+ ports for the two Ethernet channels.
|
||
Because SFP+ ports can be used for either 1 Gigabit (SFP) or 10 Gigabit (SFP+)
|
||
transceivers, several FPGA images are shipped with UHD to determine the
|
||
behavior of the above interfaces.
|
||
|
||
Interfaces can be used for either 1 Gigabit Ethernet, 10 Gigabit Ethernet,
|
||
Aurora (using 10 Gigabit speeds), and White Rabbit (the White Rabbit interface
|
||
does *not* support streaming, it only provides a time reference). See also
|
||
\ref n3xx_synchronization_whiterabbit. We provide the following flavors of FPGA
|
||
images in our default image set:
|
||
|
||
| FPGA Image Flavor | SFP+ Port 0 Interface | SFP+ Port 1 Interface |
|
||
|---------------------|------------------------|------------------------|
|
||
| HG (Default) | 1 Gigabit Ethernet | 10 Gigabit Ethernet |
|
||
| XG | 10 Gigabit Ethernet | 10 Gigabit Ethernet |
|
||
| HA | 1 Gigabit Ethernet | Aurora |
|
||
| XA | 10 Gigabit Ethernet | Aurora |
|
||
| AA | Aurora | Aurora |
|
||
| WX | White Rabbit | 10 Gigabit Ethernet |
|
||
|
||
The N320 has an additional QSFP port, and therefore has additional FPGA flavors
|
||
(AQ, XQ). For more information on those, see \ref n3xx_rh_sfp_protocols.
|
||
|
||
\section n3xx_usage Using an N3XX USRP from UHD
|
||
|
||
Like any other USRP, all N3XX USRPs are controlled by the UHD software. To
|
||
integrate a USRP N3XX into your C++ application, you would generate a UHD
|
||
device in the same way you would for any other USRP:
|
||
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||
auto usrp = uhd::usrp::multi_usrp::make("type=n3xx");
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
For a list of which arguments can be passed into make(), see Section
|
||
\ref n3xx_usage_device_args.
|
||
|
||
\subsection n3xx_usage_device_args Device arguments
|
||
|
||
Key | Description | Supported Devices | Example Value
|
||
-----------------------|------------------------------------------------------------------------------|-------------------|---------------------
|
||
addr | IPv4 address of primary SFP+ port to connect to. | All N3xx | addr=192.168.30.2
|
||
second_addr | IPv4 address of secondary SFP+ port to connect to. | All N3xx | second_addr=192.168.40.2
|
||
mgmt_addr | IPv4 address or hostname which to connect the RPC client. Defaults to `addr'.| All N3xx | mgmt_addr=ni-sulfur-311FE00 (can also go to RJ45)
|
||
find_all | When using broadcast, find all devices, even if unreachable via CHDR. | All N3xx | find_all=1
|
||
force_reinit | Force full reinitialization of all subsystems. Will increase init time. | N310 | force_reinit=1
|
||
master_clock_rate | Master Clock Rate in Hz | N310 | master_clock_rate=125e6
|
||
identify | Causes front-panel LEDs to blink. The duration is variable. | N310 | identify=5 (will blink for about 5 seconds)
|
||
serialize_init | Force serial initialization of motherboards. | All N3xx | serialize_init=1
|
||
skip_init | Skip the initialization process for the device. | All N3xx | skip_init=1
|
||
time_source | Specify the time (PPS) source. | All N3xx | time_source=internal
|
||
clock_source | Specify the reference clock source. | All N3xx | clock_source=internal
|
||
ref_clk_freq | Specify the external reference clock frequency, default is 10 MHz. | N310 | ref_clk_freq=20e6
|
||
init_cals | Specify the bitmask for initial calibrations of the RFIC. | N310 | init_cals=BASIC
|
||
init_cals_timeout | Timeout for initial calibrations in milliseconds. | N310 | init_cals_timeout=45000
|
||
discovery_port | Override default value for MPM discovery port. | All N3xx | discovery_port=49700
|
||
rpc_port | Override default value for MPM RPC port. | All N3xx | rpc_port=49701
|
||
tracking_cals | Specify the bitmask for tracking calibrations of the RFIC. | N310 | tracking_cals=ALL
|
||
rx_lo_source | Initialize the source for the RX LO. | N310 | rx_lo_source=external
|
||
tx_lo_source | Initialize the source for the TX LO. | N310 | tx_lo_source=external
|
||
rfic_digital_loopback | Digital data loopback inside the RFIC. | N310 | rfic_digital_loopback=1
|
||
tx_gain_profile | Initialize device with a specific TX gain profile. | N310 | tx_gain_profile=manual
|
||
rx_gain_profile | Initialize device with a specific RX gain profile. | N310 | rx_gain_profile=manual
|
||
tx_band_map | Semicolon-separated list of TX band edges. | N310 | tx_band_map=0.0;723.18e6;1623.18e6;3323.18e6
|
||
rx_band_map | Semicolon-separated list of RX band edges. | N310 | rx_band_map=0.0;431e6;601e6;1051e6;1601e6;2101e6;2701e6
|
||
|
||
\subsection n3xx_usage_init Device Initialization
|
||
|
||
To maximally speed up UHD, an initialization sequence is run when the device
|
||
(or more accurately, the MPM service) starts. This means even on the first run
|
||
of UHD, the device will already be initialized into a usable state. Note that
|
||
it will always come up in a default state, which can be changed by modifying the
|
||
configuration file in `/etc/uhd/mpm.conf` (see also \ref page_configfiles),
|
||
such as this:
|
||
|
||
~~~{.ini}
|
||
; Note: To boot into a fully initialized state, a clock reference must be
|
||
; connected before turning the device on if it set to external here:
|
||
[n3xx]
|
||
clock_source=external
|
||
~~~
|
||
|
||
If you prefer not to have the device initialize on boot, but rather have a fast
|
||
boot time, add the line `skip_boot_init=1` to your `/etc/uhd/mpm.conf` file.
|
||
This will force a full initialization of the device the first time a UHD session
|
||
is started, rather than during device boot.
|
||
|
||
For more details on the initialization sequence, see the corresponding section
|
||
for the specific N3XX device:
|
||
- \ref n3xx_mg_initialization
|
||
|
||
|
||
\subsection n3xx_usage_subdevspec Subdev Specifications
|
||
|
||
The RF ports on the front panel of the N300/N310 correspond to the following
|
||
subdev specifications:
|
||
|
||
Label | Subdev Spec
|
||
------|------------
|
||
RF0 | A:0
|
||
RF1 | A:1
|
||
RF2 | B:0 (N310 only)
|
||
RF3 | B:1 (N310 only)
|
||
|
||
The RF ports on the front panel of the N320/N321 correspond to the following
|
||
subdev specifications:
|
||
|
||
Label | Subdev Spec
|
||
------|------------
|
||
RF0 | A:0
|
||
RF1 | B:0
|
||
|
||
Note: Before UHD 3.12.0.0, the subdev spec options were different (A:0, B:0,
|
||
etc.). Make sure to update your application if you migrated from an earlier UHD
|
||
version.
|
||
|
||
The following example will map RF0 onto channel 0 of a uhd::usrp::multi_usrp
|
||
object, and RF3 onto channel 1:
|
||
|
||
~~~~~{.cpp}
|
||
auto usrp = uhd::usrp::multi_usrp("type=n3xx");
|
||
usrp->set_rx_subdev_spec("A:0 B:1");
|
||
// This line will now set the gain for RF3 to 20.0:
|
||
usrp->set_rx_gain(20.0, 1);
|
||
// And this will affect RF0:
|
||
usrp->set_rx_gain(20.0, 0);
|
||
~~~~~
|
||
|
||
See also uhd::usrp::subdev_spec_t.
|
||
|
||
\subsection n3xx_usage_sensors The sensor API
|
||
|
||
Like other USRPs, the N3x0 series have daughterboard and motherboard sensors.
|
||
When using uhd::usrp::multi_usrp, the following API calls are relevant to
|
||
interact with the sensor API:
|
||
|
||
- uhd::usrp::multi_usrp::get_mboard_sensor_names()
|
||
- uhd::usrp::multi_usrp::get_mboard_sensor()
|
||
- uhd::usrp::multi_usrp::get_tx_sensor_names()
|
||
- uhd::usrp::multi_usrp::get_rx_sensor_names()
|
||
- uhd::usrp::multi_usrp::get_tx_sensor()
|
||
- uhd::usrp::multi_usrp::get_rx_sensor()
|
||
|
||
The following motherboard sensors are always available:
|
||
|
||
- `ref_locked`: This will check that all the daughterboards have locked to the
|
||
external reference.
|
||
- `temp`: The temperature of the die itself
|
||
- `fan`: The current fan speed
|
||
- `gps_locked`: GPS lock
|
||
- `gps_time`: GPS time in seconds sin ce the epch
|
||
- `gps_tpv`: A TPV report from GPSd serialized as JSON
|
||
- `gps_sky`: A SKY report from GPSd serialized as JSON
|
||
|
||
|
||
\section n3xx_rasm Remote Management
|
||
|
||
\subsection n3xx_rasm_mender Mender: Remote update capability
|
||
|
||
Mender is a third-party software that enables remote updating of the root
|
||
file system without physically accessing the device (see also the
|
||
[Mender website](https://mender.io)). Mender can be executed locally on the
|
||
device, or a Mender server can be set up which can be used to remotely update
|
||
an arbitrary number of USRP devices. Mender servers can be self-hosted, or
|
||
hosted by Mender (see [mender.io](https://mender.io) for pricing and
|
||
availability).
|
||
|
||
When updating the file system using Mender, the tool will overwrite the root file
|
||
system partition that is not currently mounted (note: every SD card comes with
|
||
two separate root file system partitions, only one is ever used at a single
|
||
time). Any data stored on that partition will be permanently lost. After
|
||
updating that partition, it will reboot into the newly updated partition. Only
|
||
if the update is confirmed by the user, the update will be made permanent. This
|
||
means that if an update fails, the device will be always able to reboot into the
|
||
partition from which the update was originally launched (which presumably is in
|
||
a working state). Another update can be launched now to correct the previous,
|
||
failed update, until it works.
|
||
See also Section \ref n3xx_sdcard.
|
||
|
||
To initiate an update from the device itself, download a Mender artifact
|
||
containing the update itself. These are files with a `.mender` suffix.
|
||
|
||
Then run mender on the command line:
|
||
|
||
$ mender install /path/to/latest.mender
|
||
|
||
The artifact can also be stored on a remote server:
|
||
|
||
$ mender install http://server.name/path/to/latest.mender
|
||
|
||
This procedure will take a while. After mender has logged a successful update,
|
||
reboot the device:
|
||
|
||
$ reboot
|
||
|
||
If the reboot worked, and the device seems functional, commit the changes so
|
||
the boot loader knows to permanently boot into this partition:
|
||
|
||
$ mender commit
|
||
|
||
To identify the currently installed Mender artifact from the command line, the
|
||
following file can be queried:
|
||
|
||
$ cat /etc/mender/artifact_info
|
||
|
||
If you are running a hosted server, the updates can be initiated from a web
|
||
dashboard. From there, you can start the updates without having to log into the
|
||
device, and can update groups of USRPs with a few clicks in a web GUI. The
|
||
dashboard can also be used to inspect the state of USRPs. This is a simple way
|
||
to update groups of rack-mounted USRPs with custom file systems.
|
||
|
||
\subsection n3xx_rasm_salt Salt: Remote configuration management and execution
|
||
|
||
Salt (also known as SaltStack, see [Salt Website](https://saltstack.com)) is a
|
||
Python-based tool for maintaining fleets of remote devices. It can be used to
|
||
manage USRP N3XX series remotely for all types of settings that are not
|
||
controlled by UHD. For example, if an operator would like to reset the root
|
||
password on multiple devices, or install custom software, this tool might be a
|
||
suitable choice.
|
||
|
||
Salt is a third-party project with its [own documentation](https://docs.saltstack.com/en/latest/),
|
||
which should be consulted for configuring it. However, the Salt minion is
|
||
installed by default on every N3XX device. To start it, simply log on to the
|
||
device and run:
|
||
|
||
$ systemctl start salt-minion
|
||
|
||
To permanently enable it at every boot, run (this won't by itself launch the
|
||
salt-minion):
|
||
|
||
$ systemctl enable salt-minion
|
||
|
||
To make use of Salt, both the device needs to be configured (the "minion") and,
|
||
typically, a server to act as the Salt master. Refer to the Salt documentation
|
||
on how to configure the minion and the master. A typical sequence to get started
|
||
will look like this:
|
||
|
||
1. Install the salt-master package on the server (e.g. by running `apt install salt-master`
|
||
if the server is an Ubuntu system), and make sure the Salt master is running.
|
||
2. Add the network address / hostname of that server to the `/etc/salt/minion`
|
||
file on the device by editing the `master:` line.
|
||
3. Launch the Salt minion on the USRP by running the command `systemctl start salt-minion`.
|
||
4. The minion will try to connect to the master. You need to authorize the
|
||
minion by running `salt-key -a $hostname` where `$hostname` is the name of
|
||
the minion.
|
||
5. Once the device is authorized, you can try various commands to see if the
|
||
communication was established:
|
||
|
||
|
||
$ [sudo] salt '*' test.ping
|
||
ni-n3xx-311FE00:
|
||
True
|
||
$ [sudo] salt '*' network.interfaces
|
||
ni-n3xx-311FE00:
|
||
----------
|
||
eth0:
|
||
----------
|
||
hwaddr:
|
||
02:00:03:11:fe:00
|
||
inet:
|
||
|_
|
||
----------
|
||
address:
|
||
10.16.32.113
|
||
broadcast:
|
||
10.16.33.255
|
||
label:
|
||
eth0
|
||
netmask:
|
||
255.255.254.0
|
||
up:
|
||
True
|
||
$ [...]
|
||
|
||
|
||
\section n3xx_synchronization Clock/Time Synchronization
|
||
|
||
\subsection n3xx_synchronization_overview Overview
|
||
|
||
To choose a source for clock (frequency) and PPS (time), use the `clock_source`
|
||
and `time_source` device arguments just like with any other USRP (see also
|
||
\ref page_sync). The following combinations are supported:
|
||
|
||
`clock_source` | `time_source` | Notes
|
||
----------------|----------------|---------------------------------------------
|
||
`internal` | `internal` | Default value
|
||
`external` | `internal` | The PPS will be generated from the reference signal, but this does not allow time synchronization between devices.
|
||
`external` | `external` | The device assumes that the external reference clock and PPS are synchronized.
|
||
`gpsdo` | `gpsdo` | This will work even without GPS reception (see below).
|
||
|
||
The combination of `clock_source=external,time_source=gpsdo` is not available
|
||
out of the box, but can be enabled by patching the MPM source code (n3xx.py).
|
||
This is considered an advanced and unsupported use case. Read the appropriate
|
||
source code for a description of drawbacks. Using this mode will cause unreliable
|
||
phase alignment.
|
||
|
||
See the following sections for more details on the individual synchronization
|
||
options.
|
||
|
||
\subsection n3xx_synchronization_internal Internal references
|
||
|
||
The N3xx series has an onboard GPSDO as well as a 25 MHz reference oscillator,
|
||
which can both be used as time- and clock references. The GPSDO will function
|
||
as a reference even when there is no GPS reception. It can be powered off to
|
||
reduce power usage and interference by supplying the `enable_gps=0` option in
|
||
the configuration file (in this case, `gpsdo` cannot be used as a time or clock
|
||
reference).
|
||
|
||
Note that this does not enable the synchronization of multiple devices.
|
||
Using an internal reference is the default.
|
||
|
||
\subsection n3xx_synchronization_external External references
|
||
|
||
In order to synchronize multiple USRPs, an external reference, such as the
|
||
CDA-2990 (OctoClock), is required. If only a clock reference is available, it is
|
||
possible to derive an internal PPS signal from the reference (which will allow
|
||
devices to share a frequency, but not a time reference). If both an external
|
||
clock and time source are provided, devices will be synchronized in frequency
|
||
and time.
|
||
|
||
```cpp
|
||
auto usrp = uhd::usrp::multi_usrp::make(
|
||
"type=n3xx,clock_source=external,time_source=external");
|
||
```
|
||
To reduce phase noise, it may be necessary to power down the GPSDO when using
|
||
an external reference. To do this, just add `enable_gps=False` to the
|
||
configuration file in `/etc/uhd/mpm.conf` (see also \ref page_configfiles).
|
||
|
||
|
||
Note: When disabling the GPS with `enable_gps=0` in the configuration file, or
|
||
when manually launching MPM, the `gpsdo` reference source is not available.
|
||
|
||
\subsection n3xx_synchronization_whiterabbit White Rabbit
|
||
|
||
White Rabbit is an Ethernet-based synchronization procedure; it is an extension
|
||
of the IEEE 1588 Precision Time Protocol (PTP). The N3xx device can be
|
||
configured as a White Rabbit slave.
|
||
|
||
To use White Rabbit, it is necessary to provide an appropriate reference via
|
||
Ethernet. This reference must be connected to SFP0. Finally, a White Rabbit-compatible
|
||
FPGA must be loaded. SFP0 will *not be available for data transport* in this mode.
|
||
|
||
The White Rabbit image is provided as a default image. To obtain the default
|
||
images, simply run:
|
||
|
||
$ uhd_images_downloader -t n3xx -t fpga
|
||
|
||
Then, you can install the WX (or WA) image using `uhd_image_loader`:
|
||
|
||
$ uhd_image_loader \
|
||
--args type=n3xx,addr=ni-n3xx-<DEVICE_SERIAL>,WX
|
||
|
||
Once the image is loaded, select `internal` as the clock source and
|
||
`sfp0` as the time source (note: this will fail if the WX or WA image is not
|
||
currently loaded):
|
||
|
||
```cpp
|
||
auto usrp = uhd::usrp::multi_usrp::make(
|
||
"type=n3xx,clock_source=internal,time_source=sfp0");
|
||
// Or if you want to change it to White Rabbit after initialization:
|
||
usrp->set_sync_source(device_addr_t("clock_source=internal,time_source=sfp0"));
|
||
// Using the older time/clock source APIs is also possible:
|
||
usrp->set_time_source("sfp0");
|
||
usrp->set_clock_source("internal");
|
||
// The 2nd call can technically be skipped because the device implementations
|
||
// will coerce, but for consistency with other code and for being explicit this
|
||
// is the preferred way. The 2nd call will immediately return in this case.
|
||
```
|
||
|
||
For more information, refer to the [White Rabbit Homepage](https://www.ohwr.org/projects/white-rabbit),
|
||
or the [Ettus Research Knowledge Base](https://kb.ettus.com/Using_Ethernet-Based_Synchronization_on_the_USRP%E2%84%A2_N3xx_Devices).
|
||
|
||
\section n3xx_fpgio The Front-Panel GPIO
|
||
|
||
\b Note: The N321 does not have a front-panel GPIO due to lack of panel space.
|
||
|
||
\b Note: Do not source high currents (more than 5 mA) per pin. The GPIOs are not
|
||
designed to drive high loads!
|
||
|
||
\b Note: Unlike the X300 series, the N3XX series does not have user-programmable
|
||
daughterboard GPIOs. The front-panel GPIOs can still be used to track the ATR
|
||
state of the radios, though (see below).
|
||
|
||
The USRP N3xx series has 12 programmable GPIO pins, accessible through the DB15
|
||
connector on the front panel. The front-panel GPIO on the N3xx series has a
|
||
programmable source per pin. For every pin, it is possible to either drive it
|
||
from the PS (i.e., from Linux), or via UHD.
|
||
|
||
When UHD is driving a pin, each one of the radios (up to four in the case of the
|
||
N310) can drive the GPIO pin. In that case, the pin can either track the ATR
|
||
register of that radio channel, or it can be freely programmed.
|
||
|
||
When the PS is driving the pin, UHD releases control of the GPIO pin and it can
|
||
be programmed from Linux using udev.
|
||
|
||
The following example demonstrates how the GPIO can be used:
|
||
|
||
~~~{.cpp}
|
||
auto usrp = uhd::usrp::multi_usrp::make("type=n3xx");
|
||
auto banks = usrp->get_gpio_src_banks();
|
||
// banks[0] == "FP0"
|
||
auto gpio_src = usrp->get_gpio_src("FP0");
|
||
// Pin 0 shall be controlled by the PS:
|
||
gpio_src[0] = "PS";
|
||
// Pin 1 and 2 shall be controlled by channel 0:
|
||
gpio_src[1] = "RF0";
|
||
gpio_src[2] = "RF0";
|
||
// Pin 3 shall be controlled by channel 1:
|
||
gpio_src[3] = "RF1";
|
||
// Now update who is driving which pin:
|
||
usrp->set_gpio_src("FP0", gpio_src);
|
||
// Pin 0 is no longer accessible from UHD.
|
||
// Pin 1 shall go high when channel 0 is receiving, or during full-duplex
|
||
// Pin 2 shall be hard-coded to go high (GPIO mode)
|
||
usrp->set_gpio_attr("FP0A", "CTRL", 0x2, 0x6); // 1 == ATR, 0 == GPIO
|
||
// Set the pins to be outputs:
|
||
usrp->set_gpio_attr("FP0A", "DDR", 0x6, 0x6); // 1 == output, 0 == input
|
||
// ATR on pin 1 is off when not receiving:
|
||
usrp->set_gpio_attr("FP0A", "ATR_0X", 0x0, 0x2);
|
||
usrp->set_gpio_attr("FP0A", "ATR_TX", 0x0, 0x2);
|
||
usrp->set_gpio_attr("FP0A", "ATR_RX", 0x2, 0x2);
|
||
usrp->set_gpio_attr("FP0A", "ATR_XX", 0x2, 0x2);
|
||
// Hard-code pin 2 to stay high:
|
||
usrp->set_gpio_attr("FP0A", "OUT", 0x4, 0x4);
|
||
~~~
|
||
|
||
|
||
\section n3xx_troubleshooting Troubleshooting
|
||
|
||
\subsection n3xx_troubleshooting_seqerrs Errors while streaming
|
||
|
||
If you are getting sequence or other errors while streaming, make sure the MTU
|
||
settings of the network devices match up. UHD will try and do an automatic MTU
|
||
discovery, but there are cases when the automatic MTU discovery will yield
|
||
incorrect values. Often, the host computer MTU is set smaller than the device
|
||
MTU, but the MTU discovery will detect a larger MTU than the host computer MTU
|
||
in this error case.
|
||
|
||
The default MTU for the N3x0 series is 9000. The simplest solution is often to
|
||
set the host computer MTU to 9000 as well:
|
||
|
||
$ [sudo] ifconfig eth0 mtu 9000 # Replace eth0 with the device you're using
|
||
|
||
Of course, you can also reduce the MTU on the device to match your host
|
||
computer, see Section \ref n3xx_getting_started_connectivity.
|
||
|
||
\subsection n3xx_troubleshooting_bist Built-in Self-Test (BiST)
|
||
|
||
The N3x0 series devices have a built-in self-test that can be used to verify
|
||
the hardware. It is not automatically run, but it can be invoked anytime by
|
||
running the `n3xx_bist` executable. Calling
|
||
|
||
n3xx_bist -h
|
||
|
||
will list the available options. Tests can be run by specifying their name, e.g.
|
||
|
||
n3xx_bist gpsdo
|
||
|
||
will test the functionality of the GPSDO. Calling `n3xx_bist standard` will run
|
||
a standard set of tests, verifying some base peripherals such as the RTC, the
|
||
fan and temperature sensors, etc.
|
||
|
||
Some tests require special hardware connected. For example, there are multiple
|
||
tests to verify the SFP+ adapters. There are two types of test for those: For
|
||
the `sfp0_loopback` and `sfp1_loopback` tests, a loopback module must be plugged
|
||
into the SFP+. For the `sfp_loopback` test, the two ports need to be connected
|
||
together.
|
||
|
||
Tests may also load different FPGA images, if required. The aforementioned
|
||
SFP tests will load the AA FPGA image and use Aurora to run the BER tests on
|
||
the SFP ports. This is particularly relevant if either a custom image was
|
||
loaded, or if there is an active SSH or other connection coming in via the SFP+
|
||
ports.
|
||
|
||
\section n3xx_theory_of_ops Theory of Operation
|
||
|
||
The N3xx-series are devices based on the MPM architecture (see
|
||
also: \ref page_mpm). Inside the Linux operating system running on the ARM
|
||
cores, there is hardware daemon which needs to be active in order for the
|
||
device to function as a USRP (it is enabled to run by default).
|
||
|
||
A large portion of hardware-specific setup is handled by the daemon.
|
||
|
||
\section n3xx_fsbuild Building custom filesystems and SD card images
|
||
|
||
Ettus Research provides SD card images at regular intervals, but there can be
|
||
good reasons to build custom SD cards, e.g., to test the very latest UHD or MPM
|
||
for which there has not been an SD card release, to add own applications to the
|
||
SD card, or to run a modified version of UHD.
|
||
|
||
Note that building SD cards is very disk space and RAM intensive.
|
||
|
||
\subsection n3xx_fsbuild_docker Using Docker to build filesystems
|
||
|
||
Ettus Research provides a Docker containers to facilitate building filesystems.
|
||
Refer to the <a href="https://github.com/EttusResearch/ettus-docker/blob/master/oe-build/README.md"> README </a> for more details.
|
||
|
||
\section n3xx_software_dev Modifying and compiling UHD and MPM for the N3XX
|
||
|
||
N3xx devices ship with all relevant software installed on the SD card. Updating
|
||
UHD and/or MPM on the SD card is typically easiest done by updating the
|
||
filesystem image (see Section \ref n3xx_rasm_mender). However, it is certainly
|
||
possible to compile UHD and MPM by hand, e.g., in order to modify and try out
|
||
changes without having to build entire filesystems in between. At Ettus R&D,
|
||
this mode of operation is often used for rapid iteration cycles.
|
||
|
||
\subsection n3xx_software_dev_mpm_native Compiling MPM natively
|
||
|
||
In general, compiling natively is not a recommended way of compiling code for
|
||
the ARM processors. However, in the case of MPM, the amount of C++ code that
|
||
needs to be compiled is very little, and a full compile of MPM will take a few
|
||
minutes even on the N3xx. First, you need to get a copy of the MPM source code
|
||
onto your device. If you have an internet connection, you can use git to pull
|
||
it directly from the Ettus repository (all commands are run on the device
|
||
itself, inside the home directory):
|
||
|
||
$ git clone https://github.com/EttusResearch/uhd.git
|
||
|
||
You can also SSHFS it from another computer:
|
||
|
||
$ mkdir uhd # Create a new, empty directory called uhd
|
||
$ sshfs user@yourcomputer:src/uhd uhd # This will mount ~/src/uhd from the remote machine to ~/uhd on the N3xx
|
||
|
||
Now, create a build directory and use the regular cmake/make procedure to kick
|
||
off a build. It can be advantageous (especially for slow network connections)
|
||
to create the build directory outside of the repository directory:
|
||
|
||
$ mkdir build_mpm
|
||
$ cd build_mpm # You are now in /home/root/build_mpm
|
||
$ cmake ../uhd/mpm
|
||
$ make -j2 install # This will take several minutes
|
||
|
||
Note that this overwrites your system MPM. You can install MPM to another
|
||
location by specifying `-DCMAKE_INSTALL_PREFIX`, but make sure to update all of
|
||
your paths appropriately.
|
||
|
||
If you prefer cross-compiling MPM the same way as UHD, refer to the following
|
||
sections and adapt the instructions for UHD appropriately.
|
||
|
||
\subsection n3xx_software_dev_sdk Obtaining an SDK
|
||
|
||
The recommended way to develop software for the N3xx is to cross-compile. By
|
||
running the compiles on a desktop or laptop computer, you will be able to speed
|
||
up compile times considerably (compiling UHD natively for the N3xx would take
|
||
many hours).
|
||
|
||
SDKs are distributed along with other binaries. They contain a cross-compiler,
|
||
a cross-linker, a cross-debugger, and all the libraries available on the device
|
||
to mirror its environment.
|
||
|
||
The SDK is shipped in the same way as the other binaries, and you can download
|
||
the correct version using `uhd_images_downloader`
|
||
|
||
$ uhd_images_downloader -t sdk -t n3xx
|
||
|
||
To unpack and install the SDK, simply execute it after downloading it:
|
||
|
||
$ cd /usr/local/share/uhd/images # Change this to where your images are stored
|
||
$ ./oecore-x86_64-cortexa9hf-neon-toolchain-nodistro.0.sh
|
||
|
||
If this doesn't work, the executable permissions of the file might have been
|
||
lost (this can occur with some versions of Python). In that case, add those
|
||
permissions back before executing the `.sh` file:
|
||
|
||
$ chmod +x oecore-x86_64-cortexa9hf-neon-toolchain-nodistro.0.sh
|
||
|
||
Executing the `.sh` file will prompt you for an installation path. Please
|
||
ensure you have sufficient disk space, as each of the SDKs may require several
|
||
gigabytes of disk space (depending on the image flavor selected).
|
||
|
||
This will allow you to compile UHD as well as (depending on the image flavor)
|
||
other software, such as GNU Radio.
|
||
|
||
Please note, that while several toolchains can be installed in parallel, they
|
||
have to be installed to different directories.
|
||
|
||
\subsection n3xx_software_dev_sdkusage SDK Usage
|
||
|
||
Having installed the toolchain in the last step,
|
||
in order to build software for your device open a new shell and type:
|
||
|
||
$ . $SDKPATH/environment-setup-armv7ahf-vfp-neon-oe-linux-gnueabi
|
||
|
||
This will modify the PATH, CC, CXX etc, environment variables and allow you to compile software for your USRP N3xx device.
|
||
To verify all went well you can try:
|
||
|
||
$ $CC -dumpmachine
|
||
|
||
which should return 'arm-oe-linux-gnueabi'.
|
||
|
||
\subsubsection n3xx_software_dev_uhd Building UHD
|
||
|
||
-# Obtain the UHD source code via git or tarball
|
||
-# Set up your environment as described in \ref n3xx_software_dev_sdkusage
|
||
-# Type the following in the build directory (assuming a build in host/build):
|
||
|
||
$ cmake -DCMAKE_TOOLCHAIN_FILE=../host/cmake/Toolchains/oe-sdk_cross.cmake -DCMAKE_INSTALL_PREFIX=/usr .. # Add any CMake options you desire
|
||
$ make # You can run make -j12 to compile on 12 processes at once
|
||
|
||
Note: The UHD you are cross-compiling will not run on your host computer (the
|
||
one where you're doing the development). Compiling UHD regularly on your host
|
||
computer (with MPMD enabled) will allow you to talk to your N3xx.
|
||
|
||
\subsubsection n3xx_software_dev_gr Building GNU Radio
|
||
|
||
-# Obtain the GNU Radio source code via git or tarball
|
||
-# Set up your environment as described in \ref n3xx_software_dev_sdkusage
|
||
-# Use the following commands to create a build directory, configure and compile gnuradio. You only need create the build directory once.
|
||
|
||
\code{.sh}
|
||
$ mkdir build-arm
|
||
$ cd build-arm
|
||
$ cmake -Wno-dev -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchains/oe-sdk_cross.cmake \-DCMAKE_INSTALL_PREFIX=/usr -DENABLE_GR_VOCODER=OFF -DENABLE_GR_ATSC=OFF \
|
||
-DENABLE_GR_DTV=OFF -DENABLE_DOXYGEN=OFF ../ # Append any CMake options you desire
|
||
\endcode
|
||
|
||
Several GNU Radio components depend on running binaries built for the build
|
||
machine during compile. These binaries can be built and used for cross
|
||
compiling, but this is an advanced topic.
|
||
|
||
\section n3xx_mg N310-specific Features
|
||
|
||
\subsection n3xx_mg_panels Front and Rear Panel
|
||
|
||
Like the USRP X300 series, the N310 has connectors on both the front and back
|
||
panel. The back panel holds the power connector, all network connections, USB
|
||
connections for serial console (see \ref n3xx_getting_started_serial), JTAG,
|
||
peripherals, SMA connectors for GPS antenna input, 10 MHz clock reference,
|
||
PPS time reference input and output (TRIG in/out), the slot for the SD card
|
||
(see also \ref n3xx_sdcard), and indicator LEDs.
|
||
|
||
The following indicator LEDs are used:
|
||
|
||
- LINK: This LED will be lit when this USRP has been claimed by a UHD session.
|
||
- REF: Indicates a lock to the reference clock. In particular, when using an
|
||
external reference clock, this LED is useful to see if the LMK04828 PLLs
|
||
are locking to this reference clock. Note that some software interaction
|
||
is necessary to enable the LMK04828, and thus this LED may be off even
|
||
if a valid reference clock signal is connected.
|
||
- GPS: Indicates a GPS lock (i.e., GPS satellites are in view of the GPS
|
||
antenna and signal levels are sufficient)
|
||
- PPS: This LED will blink once every second to indicate a valid PPS signal.
|
||
|
||
\image html N310rp.png N310 Rear Panel
|
||
|
||
The front panel is used for all RF connections (including the external LO
|
||
inputs, see \ref n3xx_mg_external_lo) and all TX/RX connections, as well as the
|
||
front-panel GPIO.
|
||
|
||
The connectors labeled RF0 and RF1 are also referred to as slot A, and the
|
||
connectors labeled RF2 and RF3 are also referred as slot B (matching the
|
||
internal connections to the daughterboard. Every slot is powered by a single
|
||
AD9371 RFIC).
|
||
|
||
\image html N310fp.png N310 Front Panel
|
||
|
||
\subsection n3xx_mg_initialization Device Initialization (Fast and Slow)
|
||
|
||
When a UHD session is created, an initialization sequence is started. As part of
|
||
the initialization sequence, the following steps are performed:
|
||
|
||
- All clocking is initialized
|
||
- The JESD links are trained and brought up (between the FPGA and the AD9371)
|
||
- The AD9371 is reset, its firmware is uploaded, and calibrations are
|
||
initialized (See also \ref n3xx_mg_calibrations)
|
||
- N310 only: The multi-chip synchronization is performed to align all the RFICs
|
||
to the common time and clock reference
|
||
|
||
This sequence can take a while, depending on the master clock rate and the
|
||
calibration sequence. To speed things up, the device will retain a state
|
||
between sessions, but only if no relevant settings were touched. In particular,
|
||
changing the master clock rate, the clock source, or the calibration masks will
|
||
force a full re-initialization which is very slow compared to the fast
|
||
re-initialization. By setting the log level to DEBUG you will be able to observe
|
||
the exact settings that cause fast vs. slow re-initialization.
|
||
If you require a full re-initialization every time a UHD session is spawned,
|
||
specify the `force_reinit` flag as a device arg. Specifying it will always do
|
||
the full, slow initialization, but will guarantee a full reset of the RFIC.
|
||
|
||
To maximally speed up UHD, an initialization sequence is run when the device
|
||
(or more accurately, the MPM service) starts. This means even on the first run
|
||
of UHD, the device will already be initialized into a usable state. Note that
|
||
it will always come up in a default state, which can be changed by modifying the
|
||
configuration file in `/etc/uhd/mpm.conf` (see also \ref page_configfiles),
|
||
such as this:
|
||
|
||
~~~{.ini}
|
||
; Note: To boot into a fully initialized state, a clock reference must be
|
||
; connected before turning the device on if it set to external here:
|
||
[n3xx]
|
||
master_clock_rate=122.88e6
|
||
clock_source=external
|
||
~~~
|
||
|
||
If you prefer not to have the device initialize on boot, but rather have a fast
|
||
boot time, add the line `skip_boot_init=1` to your `/etc/uhd/mpm.conf` file.
|
||
|
||
If there are multiple N3x0 devices in a single UHD session, they will be
|
||
initialized in parallel. Note that this behaviour can be changed serial
|
||
initialization by adding `serialize_init=1` to the device args
|
||
(see \ref n3xx_usage_device_args).
|
||
|
||
\subsection n3xx_mg_calibrations RF Calibrations
|
||
|
||
The onboard RFIC (AD9371) has built-in calibrations which can be enabled from
|
||
UHD. A more detailed description of the calibrations can be found in the AD9371
|
||
user guide, see chapter "Quadrature Error Correction, Calibration, and ARM
|
||
configuration".
|
||
|
||
Not all calibrations available on the AD9371 are applicable to the USRP N310.
|
||
However, those calibrations that are applicable can be enabled/disabled at
|
||
initialization time using the `tracking_cals` and `init_cals` device args (see
|
||
also \ref n3xx_usage_device_args). These device can be set to the precise bit
|
||
mask the chip uses to set those calibrations (e.g., `init_cals=0x4DFF,tracking_cals=0xC3`)
|
||
or they can use the following descriptive keys provided by UHD
|
||
(e.g.`init_cals=DEFAULT,tracking_cals=TX_QEC|RX_QEC`). The `|` symbol can be
|
||
used to combine keys (equivalent to a bitwise OR).
|
||
|
||
Calibrations can significantly delay the initialization of a session. By only
|
||
picking relevant calibrations, sessions can be initialized faster.
|
||
|
||
Key (`init_cal`) | Function
|
||
------------------------|-----------------------------------
|
||
TX_BB_FILTER | Tx baseband filter calibration
|
||
ADC_TUNER | ADC tuner calibration
|
||
TIA_3DB_CORNER | Rx TIA filter calibration
|
||
DC_OFFSET | Rx DC offset calibration
|
||
TX_ATTENUATION_DELAY | Tx attenuation delay
|
||
RX_GAIN_DELAY | Rx gain delay calibration
|
||
FLASH_CAL | ADC flash calibration
|
||
PATH_DELAY | Path delay calibration
|
||
TX_LO_LEAKAGE_INTERNAL | Tx LO leakage internal initial calibration
|
||
TX_LO_LEAKAGE_EXTERNAL | Tx LO leakage external initial calibration (requires external LO)
|
||
TX_QEC_INIT | Tx QEC initial
|
||
LOOPBACK_RX_LO_DELAY | Loopback ORx LO delay (ORx not connected by default!)
|
||
LOOPBACK_RX_RX_QEC_INIT | Loopback Rx QEC initial calibration
|
||
RX_LO_DELAY | Rx LO delay
|
||
RX_QEC_INIT | Rx QEC initial calibration
|
||
BASIC | Preset for minimal calibrations (TX_BB_FILTER, ADC_TUNER, TIA_3DB_CORNER, DC_OFFSET and FLASH_CAL)
|
||
OFF | Preset for disabling all initial calibrations
|
||
DEFAULT | Preset for enabling most calibrations (BASIC plus TX_ATTENUATION_DELAY, RX_GAIN_DELAY, PATH_DELAY, RX_QEC_INIT, TX_LO_LEAKAGE_INTERNAL, TX_QEC_INIT, LOOPBACK_RX_LO_DELAY)
|
||
ALL | Enable all applicable calibrations
|
||
|
||
Key (`tracking_cal`) | Function
|
||
------------------------|-----------------------------------
|
||
TRACK_RX1_QEC | Rx1 QEC tracking
|
||
TRACK_RX2_QEC | Rx2 QEC tracking
|
||
TRACK_ORX1_QEC | ORx1 QEC tracking
|
||
TRACK_ORX2_QEC | ORx1 QEC tracking
|
||
TRACK_TX1_LOL | Tx1 LO leakage tracking
|
||
TRACK_TX2_LOL | Tx2 LO leakage tracking
|
||
TRACK_TX1_QEC | Tx1 QEC tracking
|
||
TRACK_TX2_QEC | Tx2 QEC tracking
|
||
OFF | Disable all tracking
|
||
RX_QEC | Enable all RX QEC tracking
|
||
TX_QEC | Enable all TX QEC tracking
|
||
TX_LOL | Enable all TX LO leakage tracking
|
||
DEFAULT | Enable all QEC tracking
|
||
ALL | Enable all tracking (except ORx)
|
||
|
||
\subsection n3xx_mg_external_lo External LOs
|
||
|
||
The N310 has inputs for external local oscillators. For every daughterboard,
|
||
there is one input for TX and RX, respectively, resulting in 4 LO inputs total
|
||
per N310.
|
||
|
||
Reasons to use an external LO include:
|
||
|
||
- Improving phase alignment: The N310 itself has no way of aligning phase
|
||
between channels, and phase will be random between runs. By applying an
|
||
external LO, the phase ambiguity is reduced to 180 degrees, produced by a
|
||
by-2 divider in the AD9371 transceiver IC.
|
||
- Improving phase noise: The quality of the onboard LO depends on the external
|
||
reference clock, among other things. By providing a custom LO signal, it is
|
||
possible to more accurately tune, assuming the externally generated LO signal
|
||
is coming from a high-quality oscillator.
|
||
|
||
|
||
\subsection n3xx_mg_eeprom Storing user data in the EEPROM
|
||
|
||
The N310 daughterboard has an EEPROM which is primarily used for storing the
|
||
serial number, product ID, and other product-specific information. However, it
|
||
can also be used to store user data, such as calibration information.
|
||
|
||
Note that EEPROMs have a limited number of write cycles, and storing user data
|
||
should happen only when necessary. Writes should be kept at a minimum.
|
||
|
||
Storing data on the EEPROM is done by loading a uhd::eeprom_map_t object into
|
||
the property tree. On writing this property, the driver code will serialize
|
||
the map into a binary representation that can be stored on the EEPROM.
|
||
|
||
\subsection n3xx_mg_revs Module and Motherboard/Daughterboard Revisions
|
||
|
||
The N310 module consists of three PCBs: The motherboard and two daughterboards.
|
||
Every PCB has a hardware revision number. Modules are always assembled such that
|
||
the daughterboards have the same revision number. The module revision number is
|
||
derived from the combination of daughterboard and motherboard hardware
|
||
revisions. The following table explains which module revision contains which
|
||
PCB revisions:
|
||
|
||
Module Revision | Motherboard Revision | Daughterboard Revision | Minimum UHD Version
|
||
----------------|----------------------|------------------------|--------------------
|
||
A | D | D | 3.11.0.0
|
||
B | F | E | 3.12.0.0
|
||
C | G | E | 3.13.0.2
|
||
D | H | E | 3.14.0.0
|
||
|
||
The module revision is printed on the sticker on the underside of an N310 module
|
||
chassis, it is contained within the part number. For example, if the sticker
|
||
says "P/N: 141064A-01L", it is a revision A module.
|
||
|
||
\subsection n3xx_mg_regmap FPGA Register Map
|
||
|
||
The following tables describe how FPGA registers are mapped into the PS.
|
||
This is for reference only, most users will not even have to know about this table.
|
||
|
||
|
||
AXI Slave | Address Range | UIO Label | Description
|
||
----------|-----------------------|------------------|-----------------------------------
|
||
Slave 0 | 4000_0000 - 4000_3fff | - | Ethernet DMA SFP0
|
||
Slave 1 | 4000_4000 - 4000_4fff | misc-enet-regs0 | Ethernet registers SFP0
|
||
Slave 2 | 4000_8000 - 4000_bfff | - | Ethernet DMA SFP1
|
||
Slave 3 | 4000_c000 - 4000_cfff | misc-enet-regs1 | Ethernet registers SFP1
|
||
Slave 4 | 4001_0000 - 4001_3fff | mboard-regs | Motherboard control
|
||
Slave 5 | 4001_4000 - 4001_41ff | dboard-regs0 | Daughterboard control, slot A
|
||
Slave 6 | 4001_8000 - 4001_bfff | dboard-regs1 | Daughterboard control, slot B
|
||
|
||
|
||
<table>
|
||
<caption id="multi_row">N310 Register Map</caption>
|
||
<tr><th>AXI Slave <th>Module <th>Address <th>Name <th>Read/Write <th>Description
|
||
<tr><td rowspan="1">Slave 0 <td rowspan="1">axi_eth_dma0 <td>4000_0000 - 4000_4fff <td>Ethernet DMA <td>RW <td>See Linux Driver
|
||
<tr><td rowspan="44">Slave 1 <td rowspan="7">n3xx_mgt_io_core <td>4000_4000 <td>PORT_INFO <td>RO <td>SFP port information
|
||
<tr> <td>[31:24] <td>COMPAT_NUM <td>RO <td>-
|
||
<tr> <td>[23:18] <td>6'h0 <td>RO <td>-
|
||
<tr> <td>[17] <td>activity <td>RO <td>-
|
||
<tr> <td>[16] <td>link_up <td>RO <td>-
|
||
<tr> <td>[15:8] <td>mgt_protocol <td>RO <td>0 - None, 1 - 1G, 2 - XG, 3 - Aurora
|
||
<tr> <td>[7:0] <td>PORTNUM <td>RO <td>-
|
||
<tr> <td rowspan="8">n3xx_mgt_io_core <td>4000_4004 <td>MAC_CTRL_STATUS <td>RW <td>Control 10gE and Aurora mac
|
||
<tr> <td>[0] <td>ctrl_tx_enable (PROTOCOL = "10GbE")<td>RW<td>-
|
||
<tr> <td>[0] <td>bist_checker_en (PROTOCOL = "Aurora")<td>RW<td>-
|
||
<tr> <td>[1] <td>bist_gen_en <td>RW <td>-
|
||
<tr> <td>[2] <td>bist_loopback_en<td>RW <td>-
|
||
<tr> <td>[8:3] <td>bist_gen_rate <td>RW <td>-
|
||
<tr> <td>[9] <td>phy_areset <td>RW <td>-
|
||
<tr> <td>[10] <td>mac_clear <td>RW <td>-
|
||
<tr> <td>n3xx_mgt_io_core <td>4000_4008 <td>PHY_CTRL_STATUS <td>RW <td>Phy reset control
|
||
<tr> <td rowspan="3">n3xx_mgt_io_core <td>4000_400C <td>MAC_LED_CTL <td>RW <td>Used by ethtool to indicate port
|
||
<tr> <td>[1] <td>identify_enable <td>RW <td>-
|
||
<tr> <td>[0] <td>identify_value <td>RW <td>-
|
||
<tr> <td rowspan="4">mdio_master <td>4000_4010 <td>MDIO_DATA <td>RW <td>-
|
||
<tr> <td>4000_4014 <td>MDIO_ADDR <td>RW <td>-
|
||
<tr> <td>4000_4018 <td>MDIO_OP <td>RW <td>-
|
||
<tr> <td>4000_401C <td>MDIO_CTRL_STATUS<td>RW <td>-
|
||
<tr> <td rowspan="4">n3xx_mgt_io_core <td>4000_4020 <td>AURORA_OVERUNS <td>RO <td>-
|
||
<tr> <td>4000_4024 <td>AURORA_CHECKSUM_ERRORS<td>RO <td>-
|
||
<tr> <td>4000_4028 <td>AURORA_BIST_CHECKER_SAMPS<td>RO <td>-
|
||
<tr> <td>4000_402C <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>-
|
||
<tr> <td rowspan="4">eth_switch <td>4000_5000 <td>MAC_LSB <td>RW <td>Device MAC LSB
|
||
<tr> <td>4000_5004 <td>MAC_MSB <td>RW <td>Device MAC MSB
|
||
<tr> <td>4000_6000 <td>IP <td>RW <td>Device IP
|
||
<tr> <td>4000_6004 <td>PORT1, PORT0 <td>RW <td>Device UDP port
|
||
<tr> <td rowspan="2">eth_dispatch <td>4000_6008 <td>[1] ndest, [0] bcast<td>RW <td>Enable Crossover
|
||
<tr> <td>4000_600c <td>[1] my_icmp_type, [0] my_icmp_code<td>
|
||
<tr> <td rowspan="5">eth_switch <td>4000_6010 <td>BRIDGE_MAC_LSB <td> <td>Bridge SFP ports in ARM
|
||
<tr> <td>4000_6014 <td>BRIDGE_MAC_MSB <td> <td>-
|
||
<tr> <td>4000_6018 <td>BRIDGE_IP <td> <td>-
|
||
<tr> <td>4000_601c <td>BRIDGE_PORT1, BRIDGE_PORT0<td> <td>-
|
||
<tr> <td>4000_6020 <td>BRIDGE_EN <td> <td>-
|
||
<tr> <td rowspan="6">chdr_eth_framer <td>4000_6108 onwards <td>LOCAL_DST_IP <td>W <td>Destination IP, MAC, UDP for Outgoing Packet for 256 SIDs
|
||
<tr> <td>4000_6208 onwards <td>LOCAL_DST_UDP_MAC_MSB<td>W <td>Destination MAC for outgoing packets (MSB)
|
||
<tr> <td>4000_6308 onwards <td>LOCAL_DST_MAC_LSB<td>W <td>Destination MAC for outgoing packets (LSB)
|
||
<tr> <td>4000_7000 onwards <td>REMOTE_DST_IP <td>W <td>Destination IP, MAC, UDP for Outgoing Packet for 16 local addrs
|
||
<tr> <td>4000_7400 onwards <td>REMOTE_DST_UDP_MAC_HI<td>W <td>Destination MAC (MSB)
|
||
<tr> <td>4000_7800 onwards <td>REMOTE_DST_MAC_LO<td>W <td>Destination MAC (LSB)
|
||
<tr><td rowspan="1">Slave 2 <td>axi_eth_dma1 <td>4000_8000 <td>- <td> <td>Same as Slave 0, different base address
|
||
<tr><td rowspan="3">Slave 3 <td>n3xx_mgt_io_core <td>4000_c001 - 4000_cfff <td>- <td>- <td>Same as Slave 1, different base address
|
||
<tr> <td>eth_dispatch <td>4000_d000 - 4000_dfff <td>- <td>- <td>Same as Slave 1, different base address
|
||
<tr> <td>eth_switch <td>4000_e000 - 4000_efff <td>- <td>- <td>Same as Slave 1, different base address
|
||
<tr><td rowspan="71">Slave 4 <td rowspan="29">n3xx_core <td>4001_0000 <td>COMPAT_NUM <td>R <td>FPGA Compat Number
|
||
<tr> <td>[31:16] <td>Major <td>RO <td>-
|
||
<tr> <td>[15:0] <td>Minor <td>RO <td>-
|
||
<tr> <td>4001_0004 <td>DATESTAMP <td>RO <td>-
|
||
<tr> <td>4001_0008 <td>GIT_HASH <td>RO <td>-
|
||
<tr> <td>4001_000C <td>SCRATCH <td>RO <td>-
|
||
<tr> <td>4001_0010 <td>REG_DEVICE_ID <td>RW <td>RFNoC Device ID
|
||
<tr> <td>4001_0014 <td>REG_RFNOC_INFO <td>RO <td>RFNoC Information
|
||
<tr> <td>[31:16] <td>CHDR_W <td>RO <td>RFNoC CHDR Width in Bits
|
||
<tr> <td>[15:0] <td>RFNOC_PROTOVER <td>RO <td>RFNoC Protocol Version
|
||
<tr> <td>4001_0018 <td>CLOCK_CTRL <td> <td>
|
||
<tr> <td>[0] <td>pps select (internal 10 MHz)<td>RW<td>One-hot encoded pps_select to use the external PPS input.
|
||
<tr> <td>[1] <td>pps select (internal 25 MHz)<td>RW<td>One-hot encoded pps_select to use the internally generated PPS with a 10 MHz ref_clk.
|
||
<tr> <td>[2] <td>pps select (external)<td>RW <td>One-hot encoded pps_select to use the internally generated PPS with a 25 MHz ref_clk.
|
||
<tr> <td>[3] <td>pps select (GPSDO)<td>RW <td>One-hot encoded pps_select to use the PPS from the GPSDO input to the FPGA.
|
||
<tr> <td>[4] <td>pps output enable<td>RW <td>
|
||
<tr> <td>[8] <td>ref clk mmcm reset<td>WO <td>-
|
||
<tr> <td>[9] <td>ref clk mmcm locked<td>RO <td>-
|
||
<tr> <td>[12] <td>meas clk mmcm reset<td>WO <td>-
|
||
<tr> <td>[13] <td>meas clk mmcm locked<td>RO <td>-
|
||
<tr> <td>4001_001C <td>XADC_READBACK <td>RO <td>-
|
||
<tr> <td>[11:0] <td>FPGA temperature<td>RO
|
||
<tr> <td>4001_0020 <td>BUS_CLK_RATE <td>RO <td>-
|
||
<tr> <td>4001_0024 <td>BUS_CLK_COUNT <td>RO <td>-
|
||
<tr> <td>4001_0028 <td>SFP_PORT0_INFO <td>RO <td>-
|
||
<tr> <td>4001_002C <td>SFP_PORT1_INFO <td>RO <td>-
|
||
<tr> <td>4001_0030 <td>FP_GPIO_MASTER <td>RO <td>GPIO master select bits. One bit per GPIO. LSB is for GPIO 0. Set bit to 0 for Radio, 1 for PS.
|
||
<tr> <td>4001_0034 <td>FP_GPIO_RADIO_SRC <td>RO <td>Radio channel source select bits. Two bits per GPIO. Bits [1:0] are for GPIO 0. Set to 00 for channel 0, 01 for channel 1, etc.
|
||
<tr> <td>4001_0048 <td>NUM_TIMEKEEPERS <td>RO <td>Number of radio timekeepers
|
||
<tr> <td rowspan="7">n3xx_mgt_io_core (NPIO0) <td>4001_0200 <td>PORT_INFO <td>RO <td>
|
||
<tr> <td>4001_0204 <td>MAC_CTRL_STATUS <td>RW <td>
|
||
<tr> <td>4001_0208 <td>PHY_CTRL_STATUS <td>RW <td>
|
||
<tr> <td>4001_0220 <td>AURORA_OVERUNS <td>RO <td>
|
||
<tr> <td>4001_0224 <td>AURORA_CHECKSUM_ERRORS<td>RO <td>
|
||
<tr> <td>4001_0228 <td>AURORA_BIST_CHECKER_SAMPS<td>RO <td>
|
||
<tr> <td>4001_022c <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>
|
||
<tr> <td rowspan="7">n3xx_mgt_io_core (NPIO1) <td>4001_0240 <td>PORT_INFO <td>RO <td>
|
||
<tr> <td>4001_0244 <td>MAC_CTRL_STATUS <td>RW <td>
|
||
<tr> <td>4001_0248 <td>PHY_CTRL_STATUS <td>RW <td>
|
||
<tr> <td>4001_0260 <td>AURORA_OVERUNS <td>RO <td>
|
||
<tr> <td>4001_0264 <td>AURORA_CHECKSUM_ERRORS<td>RO<td>
|
||
<tr> <td>4001_0268 <td>AURORA_BIST_CHECKER_SAMPS<td>RO<td>
|
||
<tr> <td>4001_026c <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>
|
||
<tr> <td rowspan="7">n3xx_mgt_io_core (QSFP0) <td>4001_0280 <td>PORT_INFO<td>RO<td>
|
||
<tr> <td>4001_0284 <td>MAC_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_0288 <td>PHY_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_02a0 <td>AURORA_OVERUNS<td>RO<td>
|
||
<tr> <td>4001_02a4 <td>AURORA_CHECKSUM_ERRORS<td>RO<td>
|
||
<tr> <td>4001_02a8 <td>AURORA_BIST_CHECKER_SAMPS<td>RO<td>
|
||
<tr> <td>4001_02ac <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>
|
||
<tr> <td rowspan="7">n3xx_mgt_io_core (QSFP1) <td>4001_02c0 <td>PORT_INFO<td>RO<td>
|
||
<tr> <td>4001_02c4 <td>MAC_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_02c8 <td>PHY_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_02e0 <td>AURORA_OVERUNS<td>RO<td>
|
||
<tr> <td>4001_02e4 <td>AURORA_CHECKSUM_ERRORS<td>RO<td>
|
||
<tr> <td>4001_02e8 <td>AURORA_BIST_CHECKER_SAMPS<td>RO<td>
|
||
<tr> <td>4001_02ec <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>
|
||
<tr> <td rowspan="7">n3xx_mgt_io_core (QSFP2) <td>4001_0300 <td>PORT_INFO<td>RO<td>
|
||
<tr> <td>4001_0304 <td>MAC_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_0308 <td>PHY_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_0320 <td>AURORA_OVERUNS<td>RO<td>
|
||
<tr> <td>4001_0324 <td>AURORA_CHECKSUM_ERRORS<td>RO<td>
|
||
<tr> <td>4001_0328 <td>AURORA_BIST_CHECKER_SAMPS<td>RO<td>
|
||
<tr> <td>4001_032c <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>
|
||
<tr> <td rowspan="7">n3xx_mgt_io_core (QSFP3) <td>4001_0340 <td>PORT_INFO<td>RO<td>
|
||
<tr> <td>4001_0344 <td>MAC_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_0348 <td>PHY_CTRL_STATUS<td>RW<td>
|
||
<tr> <td>4001_0360 <td>AURORA_OVERUNS<td>RO<td>
|
||
<tr> <td>4001_0364 <td>AURORA_CHECKSUM_ERRORS<td>RO<td>
|
||
<tr> <td>4001_0368 <td>AURORA_BIST_CHECKER_SAMPS<td>RO<td>
|
||
<tr> <td>4001_036C <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>
|
||
<tr><td rowspan="6">Slave 5 <td>4001_4000<td>4001_41FF<td>Clocking<td>see Clocking regmap<td>
|
||
<tr> <td>4001_4200<td>4001_43FF<td>Sync<td>see Sync regmap<td>
|
||
<tr> <td>4001_4400<td>4001_45FF<td>open<td>open<td>open<td>
|
||
<tr> <td>4001_4600<td>4001_47FF<td>Daughterboard <td>see Daughterboard regmap (EISCAT)<td>
|
||
<tr> <td>4001_6000<td>4001_6FFF<td>JESD Core 0<td>see JESD regmap (EISCAT)<td>
|
||
<tr> <td>4001_7000<td>4001_7FFF<td>JESD Core 1<td>see JESD regmap (EISCAT)<td>
|
||
<tr><td rowspan="1">Slave 6 <td>4001_8000 - 4001_bfff <td>see above <td>-<td>same as Slave 5<td>
|
||
</table>
|
||
|
||
\subsection n3xx_mg_eeprom_flags EEPROM flags
|
||
|
||
EEPROM flags can be set with
|
||
|
||
$ eeprom-set-flags 0xFLAGS
|
||
|
||
where FLAGS is the hex number that you can construct with the following table of bits:
|
||
|
||
| Bit | Description |
|
||
|-----|-----------------------|
|
||
| 0 | Auto-boot (1=on) |
|
||
| 2 | TPM (0=present) |
|
||
|
||
For example, to set your device to auto-boot, with TPM, the flag value is 0x1, so
|
||
|
||
$ eeprom-set-flags 0x1
|
||
|
||
\subsection n3xx_mg_gain_profiles Gain Profiles
|
||
|
||
The N310 supports four gain profiles: `default`, `manual`,
|
||
`default_rf_filter_bypass_always_on`, and `default_rf_filter_bypass_always_off`.
|
||
|
||
Usually, UHD will program individual gain components to create an overall gain
|
||
that is selected. The N310 daughterboards have three gain stages per path (two
|
||
digital step attenuators (DSAs), and one amplifier). When using the `manual`
|
||
profile, the DSAs and amplifiers can be programmed directly. In the other gain
|
||
profiles, a single, overall gain can be given, and UHD will attempt to program
|
||
the gain stages based on hard-coded gain tables. The difference between the
|
||
three "default" profiles is how the amplifier is used: Either it is always on,
|
||
always off, or it is switched on and off to optimize linearity.
|
||
|
||
\subsection n3xx_mg_custom_band_edges Custom Band Edges
|
||
|
||
\b Note: This is a highly advanced feature. Most users will not have to use this!
|
||
|
||
The N310 daughterboard splits the TX and RX paths into 4 and 7 different bands,
|
||
respectively, to hardware-optimize the RF fidelity at all available frequencies.
|
||
|
||
See the [schematics](https://kb.ettus.com/N300/N310#Schematics) for more details.
|
||
|
||
Using the `rx_band_map` and `tx_band_map` device args, it is possible to move
|
||
the band edges in software. This may be useful if the hardware was modified to
|
||
use different filters, for example, because a signal of interest always falls
|
||
onto a band edge. Using the `tx_band_map` or `rx_band_map` device arguments,
|
||
you can provide a list of lower band edges for every band. Make sure to provide
|
||
4 (for Tx) or 7 (for Rx) floating-point values. The first value should always be
|
||
zero (0.0). It may make sense to encode these values in your `uhd.conf` file:
|
||
|
||
~~~{.ini}
|
||
[type=n3xx]
|
||
rx_gain_profile=default_rf_filter_bypass_always_off
|
||
tx_gain_profile=default_rf_filter_bypass_always_on
|
||
rx_band_map=0.0;431e6;601e6;1051e6;1601e6;2101e6;2701e6
|
||
tx_band_map=0.0;723.18e6;1623.18e6;3323.18e6
|
||
~~~
|
||
|
||
In this example, the second Rx band would start at 431 MHz.
|
||
=======
|
||
\subsection n3xx_filter_api Filter API
|
||
|
||
The N300/N310 utilize the Analog Devices AD9371 AFE which contain programmable
|
||
FIR filters in both the transmit and receive paths for each of the RF channels.
|
||
These filters are available using the Digital Filter API in UHD.
|
||
|
||
| Filter Name | AD9371 Channel | Max Taps |
|
||
|-------------|----------------|----------|
|
||
| RX1_FIR | 1 | 48 |
|
||
| RX2_FIR | 2 | 48 |
|
||
| RX1RX2_FIR | 1 and 2 | 48 |
|
||
| TX1_FIR | 1 | 32 |
|
||
| TX2_FIR | 2 | 32 |
|
||
| TX1TX2_FIR | 1 and 2 | 32 |
|
||
|
||
Each filter is applied at 2x the `master_clock_rate`, or 250 MHz by default.
|
||
|
||
The Filter API also allows to set some 3 dB analog filters on the AD9371 through
|
||
the `set_tx_bandwidth` and `set_rx_bandwidth` UHD functions.
|
||
|
||
This is a small example on how to set the TX FIR and TX bandwidth.
|
||
~~~{.cpp}
|
||
// Create my USRP object
|
||
auto usrp = uhd::usrp::multi_usrp::make(args);
|
||
|
||
// Set to use channel 3
|
||
auto chan = 3;
|
||
|
||
// Set the Analog Bandwidth to be 20 MHz wide
|
||
auto bw = 20e6;
|
||
|
||
// Get the names of the filters
|
||
auto tx_names = usrp->get_tx_filter_names(chan);
|
||
|
||
// Get the first filter and print out the filter properties
|
||
auto filt = usrp->get_tx_filter(tx_names[0], chan);
|
||
|
||
// Some taps for our coefficients
|
||
const std::vector<int16_t> taps{
|
||
0,
|
||
42,
|
||
169,
|
||
374,
|
||
650,
|
||
987,
|
||
1371,
|
||
1786,
|
||
2215,
|
||
2641,
|
||
3045,
|
||
3412,
|
||
3726,
|
||
3973,
|
||
4144,
|
||
4232,
|
||
4232,
|
||
4144,
|
||
3973,
|
||
3726,
|
||
3412,
|
||
3045,
|
||
2641,
|
||
2215,
|
||
1786,
|
||
1371,
|
||
987,
|
||
650,
|
||
374,
|
||
169,
|
||
42,
|
||
0
|
||
};
|
||
|
||
// Create a custom filter with taps as our coefficients
|
||
auto filter(std::make_shared<uhd::digital_filter_fir<int16_t>>(
|
||
uhd::filter_info_base::filter_type::DIGITAL_FIR_I16,
|
||
false,
|
||
0,
|
||
1.0,
|
||
1,
|
||
1,
|
||
32767,
|
||
32,
|
||
taps)
|
||
);
|
||
|
||
// Apply the filter to the channel
|
||
usrp->set_tx_bandwidth(bw, chan);
|
||
usrp->set_tx_filter(tx_names[0], filter, chan);
|
||
~~~
|
||
|
||
\section n3xx_rh N32x-specific Features
|
||
|
||
\subsection n3xx_rh_panels Front and Rear Panel
|
||
|
||
Like the USRP X300 series, the N320/N321 has connectors on both the front and back
|
||
panel. The back panel holds the power connector, all network connections, USB
|
||
connections for serial console (see \ref n3xx_getting_started_serial), JTAG,
|
||
peripherals, SMA connectors for GPS antenna input, 10 MHz clock reference,
|
||
PPS time reference input and output (TRIG in/out), the slot for the SD card
|
||
(see also \ref n3xx_sdcard), and indicator LEDs.
|
||
|
||
The following indicator LEDs are used:
|
||
|
||
- LINK: This LED will be lit when this USRP has been claimed by a UHD session.
|
||
- REF: Indicates a lock to the reference clock. In particular, when using an
|
||
external reference clock, this LED is useful to see if the LMK04828 PLLs
|
||
are locking to this reference clock. Note that some software interaction
|
||
is necessary to enable the LMK04828, and thus this LED may be off even
|
||
if a valid reference clock signal is connected.
|
||
- GPS: Indicates a GPS lock (i.e., GPS satellites are in view of the GPS
|
||
antenna and signal levels are sufficient)
|
||
- PPS: This LED will blink once every second to indicate a valid PPS signal.
|
||
|
||
The rear panel is identical between the N320 and the N321 with the exception of
|
||
the product name above the SFP+ connectors.
|
||
|
||
\image html N320_Rear.png N320 Rear Panel
|
||
|
||
\image html N321_Rear.png N321 Rear Panel
|
||
|
||
The front panel is used for all RF connections (including the external LO
|
||
inputs, see \ref n3xx_rh_external_lo) and all TX/RX connections, as well as the
|
||
front-panel GPIO (N320 only!).
|
||
|
||
The connectors labeled RF0 are also referred to as slot A, and the connectors
|
||
labeled RF1 are also referred as slot B (matching the internal connections to
|
||
the daughterboard).
|
||
|
||
\image html N320_Front.png N320 Front Panel
|
||
|
||
\image html N321_Front.png N321 Front Panel
|
||
|
||
\subsection n3xx_rh_initialization Device Initialization (Fast and Slow)
|
||
|
||
When a UHD session is created, an initialization sequence is started. As part of
|
||
the initialization sequence, the following steps are performed:
|
||
|
||
- All clocking is initialized
|
||
- The JESD links are trained and brought up (between the FPGA and the ADC/DAC)
|
||
|
||
This sequence can take a while, depending on the master clock rate and the
|
||
calibration sequence. To speed things up, the device will retain a state
|
||
between sessions, but only if no relevant settings were touched. In particular,
|
||
changing the master clock rate or the clock source will
|
||
force a full re-initialization which is slower compared to the fast
|
||
re-initialization. By setting the log level to DEBUG you will be able to observe
|
||
the exact settings that cause fast vs. slow re-initialization.
|
||
If you require a full re-initialization every time a UHD session is spawned,
|
||
specify the `force_reinit` flag as a device arg. Specifying it will always do
|
||
the full, slow initialization, but will guarantee a full reset digital chains.
|
||
|
||
To maximally speed up UHD, an initialization sequence is run when the device
|
||
(or more accurately, the MPM service) starts. This means even on the first run
|
||
of UHD, the device will already be initialized into a usable state. Note that
|
||
it will always come up in a default state, which can be changed by modifying the
|
||
configuration file in `/etc/uhd/mpm.conf` (see also \ref page_configfiles),
|
||
such as this:
|
||
|
||
~~~{.ini}
|
||
; Note: To boot into a fully initialized state, a clock reference must be
|
||
; connected before turning the device on if it set to external here:
|
||
[n3xx]
|
||
master_clock_rate=200e6
|
||
clock_source=external
|
||
~~~
|
||
|
||
If you prefer not to have the device initialize on boot, but rather have a fast
|
||
boot time, add the line `skip_boot_init=1` to your `/etc/uhd/mpm.conf` file.
|
||
|
||
|
||
\subsection n3xx_rh_calibrations RF Calibrations
|
||
|
||
The N320/N321 can perform some simple calibration for I/Q imbalance and DC
|
||
offset, the same way as the X300 series. Refer to \ref page_calibration for more
|
||
details.
|
||
|
||
\subsection n3xx_rh_external_lo External LOs
|
||
|
||
The N320/N321 can utilize an external LO that is connected to the front panel
|
||
connectors. For the N320, the LO IN TX and LO IN RX connectors are used. For
|
||
the N321, the RX LO IN1 and TX LO IN1 connectors are used. One or both
|
||
daughterboards may use this external LO signal by setting the channel's LO
|
||
source to "external". When the source is set to "external", reading the LO
|
||
frequency will return the ideal frequency for an external LO source.
|
||
|
||
The nominal LO input level is +5 dBm. Actual LO input levels should be within
|
||
+/- 2 dB of that value (i.e., between +3 dBm and +7 dBm).
|
||
|
||
\subsection n3xx_rh_lo_sharing N321 LO Distribution Board
|
||
|
||
The N321 has an additional board to perform LO signal splitting and
|
||
distribution. The 4 output ports, OUT0 through OUT3, are driven by a 1:4
|
||
splitter which can be sourced from the corresponding IN0 front panel port or
|
||
the LO on the daughterboard in slot A. To use the IN0 front panel port, set LO
|
||
export enabled to false. To use the LO located on the daughterboard in slot A,
|
||
set LO export enabled to true.
|
||
|
||
Each of the 4 output ports, OUT0 through OUT3, have an internal terminator
|
||
which must be disabled before use. These can be controlled through the RFNoC
|
||
radio block's API, the property tree, or directly through commands in the MPM
|
||
shell.
|
||
|
||
\image html N321_LO_Distribution_Block_Diagram.png "N321 LO Distribution Diagram"
|
||
|
||
\subsection n3xx_rh_lo_chaining N320/N321 LO Sharing
|
||
|
||
By using matched length cabling with N321s, up to 16 modules can use both of
|
||
their RX and TX channels while sharing a single N321's LO signal, resulting in
|
||
a 32 by 32 channel single shared LO configuration. This 32 by 32 channel
|
||
configuration can also utilize an external LO signal, allowing an already split
|
||
external LO signal to support larger configurations of 64 by 64 channels, 128
|
||
by 128 channels, and larger.
|
||
|
||
The following diagram shows the connections necessary to create a 16 by 16
|
||
channel configuration with a single shared LO source.
|
||
|
||
\image html N321_16_Channel_Example.png "N321 16 Channel LO Sharing"
|
||
|
||
\subsection n3xx_rh_sfp_protocols SFP+ and QSFP+ protocols
|
||
|
||
The protocols supported on the SFP+ and QSFP+ ports depend on the FPGA image
|
||
currently loaded.
|
||
|
||
Interface | HG | XG | WX | XQ | AQ
|
||
-------------|--------|--------|--------------|--------------|--------
|
||
SFP+ 0 | 1 GbE | 10 GbE | White Rabbit | White Rabbit | 10 GbE
|
||
SFP+ 1 | 10 GbE | 10 GbE | 10 GbE | Unused | 10 GbE
|
||
QSFP+ lane 0 | Unused | Unused | Unused | 10 GbE | Aurora
|
||
QSFP+ lane 1 | Unused | Unused | Unused | 10 GbE | Aurora
|
||
QSFP+ lane 2 | Unused | Unused | Unused | Unused | Aurora
|
||
QSFP+ lane 3 | Unused | Unused | Unused | Unused | Aurora
|
||
|
||
\subsection n3xx_rh_frontend_corrections N320/N321 Frontend Corrections
|
||
|
||
In an unmodified FPGA image, N320/N321 perform several steps of digital signal
|
||
processing between the RFNoC Radio block and the ADC/DAC.
|
||
|
||
It should be noted that the DACs/ADCs run at twice the master clock rate (e.g.,
|
||
if the master clock rate is 250 MHz, the DACs/ADCs are clocked at 500 MHz). We
|
||
perform a sample rate conversion to the master clock rate within the FPGA.
|
||
|
||
```
|
||
┌───────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────┐
|
||
│ │ │ TX │ │TX │ │ Halfband │ 2x MCR │ │
|
||
│ ├─>│ IQ Offset ├──>│DC Offset ├─>│ Interpolator ├────────>│ DAC │
|
||
│ │ │ Compensation │ │Compensation │ │ (47 taps) │ │ │
|
||
│ RFNoC │ └──────────────┘ └─────────────┘ └──────────────┘ └─────┘
|
||
│ Radio │
|
||
│ Block │ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────┐
|
||
│ │ │ RX │ │RX │ │Halfband │ 2x MCR │ │
|
||
│ │<─┤ IQ Offset │<──┤DC Offset │<─┤Decimator │<────────┤ ADC │
|
||
│ │ │ Compensation │ │Compensation │ │(47 taps) │ │ │
|
||
└───────┘ └──────────────┘ └─────────────┘ └──────────────┘ └─────┘
|
||
```
|
||
|
||
The IQ and DC offset compensation components can be controlled from the host
|
||
side using the correction APIs. The following snippet shows the control of these
|
||
APIs from the host side using the multi_usrp APIs:
|
||
|
||
~~~{.cpp}
|
||
// Generate an N320/N321 multi_usrp object
|
||
auto usrp = uhd::usrp::multi_usrp::make("type=n3xx");
|
||
// Set TX IQ offset value on channel zero:
|
||
usrp->set_tx_iq_balance(my_tx_iq_offset_value, 0);
|
||
// Set TX DC offset value on channel zero:
|
||
usrp->set_tx_dc_offset(my_tx_dc_offset_value, 0);
|
||
// Set RX IQ offset value on channel zero:
|
||
usrp->set_tx_iq_balance(my_rx_iq_offset_value, 0);
|
||
// Enable auto-RX-DC-offset on all channels:
|
||
usrp->set_rx_dc_offset(true);
|
||
// Set RX DC offset value to specific value on channel zero:
|
||
usrp->set_tx_dc_offset(my_tx_dc_offset_value, 0);
|
||
~~~
|
||
|
||
When using the RFNoC API, use the uhd::rfnoc::radio_control API calls with the
|
||
same names.
|
||
|
||
Notes:
|
||
- Other than the RX DC offset calibration, there are no automatic compensation
|
||
procedures. N320 uses a simple, single-tap IIR filter for automatic DC offset
|
||
correction (like X310).
|
||
- The automatic RX DC offset correction acts as a notch filter around the LO
|
||
frequency.
|
||
- For more details on the internals of these corrections, see \ref calibration_fe_corr.
|
||
|
||
The halfband decimators/interpolators are not configurable. They are 47-tap
|
||
halfband filters with the following coefficients:
|
||
|
||
-62, 0, 194, 0, -440, 0, 855, 0, -1505, 0, 2478, 0, -3900, 0, 5990, 0, -9187, 0, 14632, 0, -26536, 0, 83009, 131071, 83009, 0, -26536, 0, 14632, 0, -9187, 0, 5990, 0, -3900, 0, 2478, 0, -1505, 0, 855, 0, -440, 0 194, 0, -62.
|
||
|
||
\subsection n3xx_rh_eeprom_flags EEPROM flags
|
||
|
||
EEPROM flags can be set with
|
||
|
||
$ eeprom-set-flags 0xFLAGS
|
||
|
||
where FLAGS is the hex number that you can construct with the following table of bits:
|
||
|
||
| Bit | Description |
|
||
|-----|-----------------------|
|
||
| 0 | Auto-boot (1=on) |
|
||
| 2 | TPM (0=present) |
|
||
|
||
For example, to set your device to auto-boot, with TPM, the flag value is 0x1, so
|
||
|
||
$ eeprom-set-flags 0x1
|
||
|
||
*/
|
||
// vim:ft=doxygen:
|