| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
| |
The internal helper function graph_t::_forward_edge_props() receives
another argument, which decides if properties are forwarded on forward-
or back-edges. Previously, only forward-edges were possible.
|
|
|
|
|
|
|
|
|
|
|
| |
Enabled with the "tx_replay_buffer" device argument. Buffers TX data in
DRAM using the Replay block (version 1.1 or higher required), allowing
more buffering of data on the device. May reduce underruns for certain
applications. The Replay block is currently limited to 32 play
commands, so fewer calls to send() with larger buffers will perform
better than more calls with smaller buffers.
Signed-off-by: michael-west <michael.west@ettus.com>
|
|
|
|
|
|
|
| |
- Added command time to readback of time from Radio block.
- Added wait for time to readback of shared registers in Radio block.
Signed-off-by: michael-west <michael.west@ettus.com>
|
|
|
|
|
|
| |
Add support for reading the number of supported SPI slaves from
the device. This has become necessary because we may have bitfiles
with different capabilities and we want to report this back correctly.
|
|
|
|
|
|
|
|
|
| |
- Add ability to get current record position.
- Add ability to get current play position.
- Track space in play command FIFO and throw uhd::op_failed error when
command requested would overflow the command FIFO.
Signed-off-by: michael-west <michael.west@ettus.com>
|
|
|
|
|
|
|
|
|
|
|
|
| |
For certain frequencies, the LMX2592 will sporadically fail to lock upon
the very first tune. When this happens, subsequent tunes (even to the same
frequency) do lock. This issue seems to be resolved by programming the FCAL
adjustment register fields (FCAL_LPFD_ADJ/FCAL_HPFD_ADJ) as described in
the LMX2592 datasheet. These fields adjust the FCAL calibration speed to
better accomodate PFD frequencies below 20MHz or above 100MHz.
This patch also fixes a few name typos in the register map that were
directly in the scope of this change.
|
|
|
|
|
|
| |
Log installed DPDK version on boot.
Signed-off-by: mattprost <matt.prost@ni.com>
|
|
|
|
|
|
|
|
| |
Substituting old values to restore API breakage from DPDK 18.11 to DPDK 19.
It is recommended at this point that users upgrade to more recent DPDK LTS
versions, but the DPDK 18.11 API is functional with UHD.
Signed-off-by: mattprost <matt.prost@ni.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The new API calls get_{record,play}_async_metadata() calls are now
available in Python. To look more Pythonic, we change the call signature
and return value to either return `None` or the value (if available).
For comparison, this is the C++ code:
```cpp
uhd::rx_metadata_t md;
if (replay_ctrl->get_record_async_metadata(md, 0.1)) {
cout << "Received metadata! Error code: " << md.strerror() << endl;
} else {
cout << "No metadata received!" << endl;
}
```
In Python, this has the more Pythonic form:
```python
md = replay_ctrl.get_record_async_metadata(0.1);
if md is not None:
print("Received metadata! Error code: ", md.strerror())
else:
print("No metadata received!")
```
|
|
|
|
|
|
|
| |
- Add action handlers to the replay block to store TX and RX events.
- Adds two new APIs: get_{record,play}_async_metadata() to read back
async info.
- Add unit tests.
|
| |
|
|
|
|
|
|
| |
This fixes an issue with setting the active channel source in MPM, and
additionally allows opening up the more flexible API in the future without
requiring a filesystem update.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The power that corresponds to a certain gain values depends on the
frequency band we are in. At the edges of these bands discontinuities
can occur (the gain necessary to achieve the same power value changes
non-continuously). The power calibration does a linear interpolation
between two neighbor points in the calibration data set to find at
best fitting value. We therefore have to make sure that this interpolation
does not cross discontinuities.
This is a minimal invasive approach. It adds values at discontinuities
for the lower and the upper band. The power calibration format uses
the frequency for a power to gain mapping as a map key. Therefore two
gain to power mappings cannot be stored for the same frequency as it
would be needed for the discontinuity. Instead the mapping for the
lower band is stored at the discontinuity frequency itself. The mapping
for the upper band is stored at the frequency + 1Hz. The calibration
will therefore still fail to yield proper results within this
sub-Hertz range. The frequency lookup in the power calibration manager
now uses round instead of truncation to find the best mapping frequency
in the calibration table.
With this, searching for neighbor data points now ensures that the data
points used belong to the same band (except for the range of
(f_discontinuity, f_discontinuity + 1Hz) ).
This commit does not solve the issue for calibration data generated
with usrp_power_cal.py because the Python interface has no means to
detect band edges for the USRP it is calibrating.
|
|
|
|
|
|
|
|
| |
In order to perform certain operations (start/stop/step), meta_range_t
objects must be "monotonic", meaning that the subranges composing it
are sorted and non-overlapping. This commit creates a method which
takes a non-monotonic meta_range_t containing no non-continuous
subranges and converts it into a monotonic meta_range_t.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
This is a follow-up to 930fa39, where we set the MTU property explicitly
for several blocks. The radio block should also receive this treatment,
as the IQ data going into its inputs is not forwarded to its outputs.
This patch will remove spurious log messages like these:
[INFO] [0/Radio#0] Setting default MTU forward policy.
[INFO] [0/Radio#1] Setting default MTU forward policy.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit refactors ctrlport_endpoint and fixes several issues related
to multiple threads sending and receiving control transfers.
First, it refactors the change that Martin Braun implemented in
0caed5529 by adding a tracking mechanism for control requests where
clients have explicitly asked to receive an ACK when the corresponding
control response is received.
When a client wants to wait for an ACK associated with a control
request, a combination of that request's opcode, address, and sequence
number is added to a set when the request is sent. When a control
response is received, the set is consulted to see if the corresponding
request is there by matching the packet field data listed above. If so,
the control response is added to the response queue, thus notifying all
threads waiting in `wait_for_ack()` that there is a response that the
thread may be waiting on. If the request is not in the set, the request
is never added to the response queue. This prevents the initial problem
that 0caed5529 was addressing of the response queue growing infinitely
large with control responses that would never be popped from the queue.
Secondly, it addresses issues when multiple threads have sent a request
packet and are waiting in `wait_for_ack()` on the corresponding
response.
Originally, the function contained a loop which would sleep the calling
thread until the control response queue had at least one element in it.
When awakened, the thread would pop the frontmost control response off
the queue to see if it matches the corresponding control request (i.e.,
has the same sequence number, opcode, and address elements). If so, the
response would be handled appropriately, which may include signalling an
error if the response indicates an exceptional status, and the function
would return. If the response is not a matching one, the function would
return to the top of the loop. If the corresponding response is not
found within a specified period, the function would throw an op_timeout
exception.
However, there is a subtle issue with this algorithm when two different
calling threads submit control requests and end up calling
`wait_for_ack()` nearly simultaneously. Consider two threads issuing a
control request. Thread T1 issues a request with sequence number 1 and
thread T2 issues a request with sequence number 2. The two threads then
call `wait_for_ack()`. Let's assume that neither of the control reponses
have arrived yet. Both threads sleep, waiting to be notified of a
response. Now the response for sequence number 1 arrives and is pushed
to the front the response queue. This generates a signal that awakes one
of the waiting threads, but which one is awakened is completely at the
mercy of the scheduler. If T1 is awakened first, it pops the response
from the queue, finds that it matches the request, and handles it as
expected. Later, when the reponse for sequence number 2 is pushed onto
the queue, the still-sleeping T2 will be awakened. It pops the response,
finds it to be matching, and all is well.
But if the scheduler decides to wake T2 first, T2 ends up popping the
response with sequence number 1 off the front of the queue, but it
doesn't match the request that T2 sent with sequence number 2, so T2
goes back to the top of the loop. At this point, it doesn't matter if T2
or T1 is awakened next; because the control response for sequence number
1 was already popped off the queue, T1 never sees the control response
it expects, and will throw uhd::op_timeout back up the stack.
This commit modifies the `wait_for_ack()` algorithm to search the queue
for a matching response rather than indiscriminately popping the
frontmost element from the queue and throwing it away if it doesn't
match. That way, the order in which threads are awakened no longer
matters as they will be able to find the corresponding response
regardless. Furthermore, when a response is pushed onto the response
queue, all waiting threads are notified of the condition via
`notify_all()`, rather than just waking one thread at random
(`notify_one()`). This gives all waiting threads the opportunity to
check the queue for a response.
Finally, the `wait_for_ack()` loop has been modified such that the
thread waits to be signalled regardless of whether the queue has
elements in it or not. (Prior to this change, the thread would only wait
to be signalled if the queue was empty.) This effectively implements the
behavior that all threads are awakened when a new control response is
pushed into the queue, and combined with the changes above, ensures that
all threads get a chance to react and check the queue when the queue is
modified.
|
|
|
|
|
|
|
|
| |
Make sure no active components are connected to the TX frontend during
next boot. This avoids configurations that could generate unwanted tones
during operations such as the Mykonos init cals.
Signed-off-by: mattprost <matt.prost@ni.com>
|
| |
|
|
|
|
|
|
|
| |
This adds the atomic item size property to the replay block, which was
originally introduced in 3e5e4eb. The effect is that it enforces
streaming data to and from the block that is an integer multiple of the
word size.
|
| |
|
|
|
|
|
| |
This commit modifies the explicitly written narrowing conversions to
clamp the results to the limits of the signed integer type.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit implements some minor cleanup of various converter- and
convert test-related code:
* Improves the log messages regarding which converter was returned for a
request.
* Modifies the result checking code in the converter tests to only
report an out-of-range sample error once, rather than reporting every
out-of-range sample encountered during the test. This vastly cuts down
on the output when a conversion has failed.
* Adds a function `reverse_converter()` which, given a
`convert::id_type` describing a conversion from C1 to C2, returns a
`convert::id_type` describing the reverse conversion (C2 to C1).
* Removes two redundant test cases from the converter test.
|
|
|
|
| |
Signed-off-by: Ron Economos <w6rz@comcast.net>
|
|
|
|
|
|
|
|
| |
When connecting an Rx streamer to a replay block, this now allows
requesting data from the replay block using a stream command. This will
automatically request data from all ports the streamer is connected to,
and even if there are blocks in between (depending on their action
forwarding policies).
|
|
|
|
| |
These RFNoC C++ API calls were previously not exported into Python.
|
|
|
|
|
|
|
| |
rfnoc::connect_through_blocks(), unlike rfnoc_graph::connect(), did not
have an argument to declare a back-edge. This patch remedies this
situation by adding a skip_property_propagation argument that works
exactly as with rfnoc_graph::connect().
|
|
|
|
|
|
|
| |
The FSRU (aka EISCAT) was never supported in UHD 4.0. The FPGA
repository never had the relevant files, and the block controller also
never existed. This removes all the corresponding files from MPM, as
well as some references from makefiles.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Throughout UHD, we often do floating-point comparisons for frequency
ranges that require resilience to floating point rounding errors. Most
of the time the checks look like this:
```cpp
if (fp_compare_epsilon<double>(freq) > boundary) {
// ...
}
```
The exception is the N320 daughterboard control, which uses a custom
epsilon:
```cpp
if (fp_compare_epsilon<double>(freq,
RHODIUM_FREQ_COMPARE_EPSILON) > boundary) {
// ...
}
```
This was, for the most part, not by design, but because authors simply
didn't think about which epsilon value was appropriate for the frequency
comparison. This was complicated by the fact that fp_compare_epsilon
previously had some issues.
This patch introduces FREQ_COMPARE_EPSILON, which is a sensible default
value for fp_compare_epsilon when doing frequency comparisons (note that
fp_compare_delta already had such a value).
Also, it introduces freq_compare_epsilon(x), which is a shorthand for
fp_compare_epsilon<double>(x, FREQ_COMPARE_EPSILON).
We then replace all occurrences of fp_compare_epsilon<double> which are
specific to frequency checks with freq_compare_epsilon.
|
|
|
|
|
|
| |
This changes the return value of connect_through_blocks() from void to
a list of edges. If the connection can be made, then it will now return
the list of connections between the source block and port.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes the following warnings:
```
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:2335:5: warning: \
delete called on non-final 'uhd::rfnoc::x400::x400_gpio_port_mapping' that has \
virtual functions but non-virtual destructor [-Wdelete-non-virtual-dtor]
delete __ptr;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:2648:7: note: in \
instantiation of member function 'std::__1::default_delete<uhd::rfnoc::x400::x4\
00_gpio_port_mapping>::operator()' requested here
__ptr_.second()(__tmp);
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:2602:19: note: in\
instantiation of member function 'std::__1::unique_ptr<uhd::rfnoc::x400::x400_g\
pio_port_mapping, std::__1::default_delete<uhd::rfnoc::x400::x400_gpio_port_map\
ping> >::reset' requested here
~unique_ptr() { reset(); }
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:4063:21: note: in\
instantiation of member function 'std::__1::unique_ptr<uhd::rfnoc::x400::x400_g\
pio_port_mapping, std::__1::default_delete<uhd::rfnoc::x400::x400_gpio_port_map\
ping> >::~unique_ptr' requested here
unique_ptr<_Yp> __hold(__p);
^
/Users/rfmibuild/myagent/_work/76/s/host/lib/usrp/x400/x400_radio_control.cpp:1\
92:33: note: in instantiation of function template specialization 'std::__1::sh\
ared_ptr<uhd::mapper::gpio_port_mapper>::shared_ptr<uhd::rfnoc::x400::x400_gpio\
_port_mapping>' requested here
auto gpio_port_mapper = std::shared_ptr<uhd::mapper::gpio_port_mapper>(
```
and:
```
/Users/rfmibuild/myagent/_work/76/s/host/lib/usrp/x400/x400_gpio_control.cpp:15\
4:75: warning: adding 'const uint32_t' (aka 'const unsigned int') to a string d\
oes not append to the string [-Wstring-plus-int]
"Could not find corresponding GPIO pin number for given SPI pin " + value);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/rfmibuild/myagent/_work/76/s/host/lib/usrp/x400/x400_gpio_control.cpp:15\
4:75: note: use array indexing to silence this warning
"Could not find corresponding GPIO pin number for given SPI pin " + value);
^
& [ ]
```
|
|
|
|
|
| |
This allows viewing or, conceivably, customizing the tuning table that
ZBX uses, depending on the particular needs of the end user.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Note that the default MTU forwarding policy is ONE_TO_ONE, therefore,
it is only strictly necessary to modify the MTU forwarding policy for
blocks that route data in a different manner. However, it may be nice to
explicitly state the forwarding policy for the benefit of the reader.
The following blocks had their policies updated:
- addsub: ONE_TO_FAN
- duc: ONE_TO_ONE
- dmafifo: ONE_TO_ONE
- null block: DROP
- replay block: DROP
- split stream: ONE_TO_FAN
- switchboard: ONE_TO_FAN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously, the default was DROP. For almost all RFNoC blocks, this is
not a good default. It is very easy to crash USRPs by not properly
propagating the MTU. For example, the following flow graph:
Radio -> DDC -> FIR -> Streamer
would crash an X310 when not manually setting an spp value. The reason
is: The Radio block has an output buffer of 8192 bytes, capable of
handling 2044 samples per packet. However, that's too big for the
Ethernet portion of the X310, which would cause the X310 to lose
connection between UHD and firmware. If the FIR were configured to
propagate MTU, the Host->USRP connection (which has an MTU of <= 8000)
would limit the MTU on all links, and the spp value would automatically
be reduced to 1996 (or less).
This commit uses the post_init() feature to check the user set an MTU in
the constructor, and sets it to the default if that didn't happen. This
doesn't solve all problems (the new default of ONE_TO_ONE) could also be
incorrect, but is a much more suitable default.
As a consequence, this has a minor change in how
set_mtu_forwarding_policy() can be used: It now must be called during
the constructor. Before, the rule was that it may only be called once,
but that could also have happened, e.g., during the first property
resolution. Now, the constructor is the last time block authors can
choose an MTU forwarding policy.
|
|
|
|
|
|
|
|
| |
This method allows running a fixed set of rules to check the internal
consistency of a block. This may be necessary, because blocks authors
may incorrectly implement a certain design rule, and we want the ability
to not start an RFNoC graph with blocks that have rule violations which
we can write checks for.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In 716ed77, refactoring was performed to merge `set_tx_subdev_spec()`
and `set_rx_subdev_spec()` via the use of a shared helper function,
`_set_subdev_spec()`, which factors out differences in the two
directions by accepting lambda functions from the caller. However, there
were two bugs introduced in the refactoring:
- The channel map parameter, which is either `_rx_chans` or `_tx_chans`
based on direction, was passed by value and not reference, so changes
made by the function were not persisted in the member variables
maintained in the `multi_usrp_rfnoc` class.
- The connection removal loop checks for the presence of an SEP block on
an edge as its termination condition. In the pre-refactored code, the
direction determined whether the source or destination of the edge was
checked for the SEP. However, in the refactoring, the source of the edge
is checked for both TX and RX. While this works for the
`set_tx_subdev_spec()` call, it breaks the `set_rx_subdev_spec()` call.
This commit fixes the issue by adding another lambda parameter to the
`set_subdev_spec()` function, which puts the onus of the edge check on
the direction-specific code to ensure it is looking at the correct side
of the edge.
|
|
|
|
|
|
|
|
|
|
| |
Constatntly incrementing endpoints was causing the entries in the
routing table on the device to be exhausted, eventually resulting in a
timeout error on control packets. Since a connection between the host
and a stream endpoint on a device in a given direction is unique, the
host endpoints can be cached and re-used. This change does that.
Signed-off-by: michael-west <michael.west@ettus.com>
|
|
|
|
|
|
|
|
|
|
|
|
| |
When the minor FPGA compat number on the device is ahead of what MPM
expects, we no longer print a warning. That's because by definition, the
FPGA is still compatible with the software in this case.
If UHD requires a certain minor compat number to enable a feature,
the appropriate behaviour would be to print a warning only for that
case.
This is the equivalent change to the MPM-only change in 88d28481.
|
|
|
|
|
|
| |
The FPGA GPIO registers don't exactly match the pin numbering on the
front panel and in the docs. This commit changes the algorithm so that
the API presented to the user matches the front panel.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In 0caed5529, a change was made to ctrlpoint_endpoint's behavior such
that if a client does not care about checking for ACKs on poke or poll
operations, the code calls `wait_for_ack()` with a flag indicating that
it should not wait for the ACK, but find and remove the corresponding
response from the response queue. This prevents the queue from
potentially growing endlessly with response packets that the client
doesn't even care about.
However, this introduced a subtle, undesired behavioral change. When
`wait_for_ack()` finds the corresponding response for a request, it also
checks the status field of the response to report any errors flagged by
the hardware such as invalid command, routing error, etc. Prior to the
change mentioned above, since `wait_for_ack()` was never called when the
client doesn't want ACKs, the client would never be never notified of
any errors associated with the request. However, with the aforementioned
change in placd, when `wait_for_ack()` is called to find and remove the
unwanted response packet corresponding to the request, errors **are**
checked and reported up the user.
The behavior change was unearthed by the X410 ZBX CPLD initialization
code, which writes an initial value of 0 to all ZBX CPLD registers--even
read-only registers. A control request to write a read-only register
results in a response with CMDERR in its status field, as it should.
However, since the ZBX CPLD register initialization is performed with a
`poke32()` operation which by default doesn't wait for ACKs, this was
never a problem until the change to drain the response queue
inadvertently caused the error to surface. The result is that creating a
USRP session or RFNoC graph session to an X410 device is seen to
occasionally fail with a 'RuntimeError: RuntimeError: Failure to create
rfnoc_graph' message printed to the console.
This commit preserves the desired queue-draining behavior, but ignores
any error status on the response when it is found and removed from the
queue, thus restoring the behavior pre-0caed5529.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some APIs were changed with the latest DPDK LTS release,
add some ifdefs to fix the build.
Fixes https://github.com/EttusResearch/uhd/issues/547
Updated CMake file to reflect updated DPDK version.
Fixed mbuf size to take ethernet headers into account.
Updated documentation.
Co-authored-by: Martin Anderseck <martin.anderseck@ni.com>
|
| |
|
|
|
|
|
|
| |
This resolves some linking issues across binaries.
Signed-off-by: Steven Koo <steven.koo@ni.com>
|
|
|
|
|
|
|
|
| |
This commit disables x4xx_radio_block_test on macOS
because the platform has stricter casting and symbol
export rules, which causes this test to fail.
Signed-off-by: Steven Koo <steven.koo@ni.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes multiple issues:
- The simple_claimer was not truly atomic, it tested and set the
locked-flag on separate lines
- It used a Boost yield statement, although we're not running Boost
threads
- It used the deprecated UHD_INLINE macro
We also remove spin_wait_with_timeout(), which was only used in
claim_with_wait() because it's not worth putting into its own function.
This is no API change on simple_claimer, but it may result in different
performance of this spinlock.
|