aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-08-01 14:51:31 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:34 -0800
commit1e51dd7774017cbad84315284596417636ab044d (patch)
tree689d32b7b55e51c26871ef1ae9364cf00dba4bc0
parentb89c53c0691c6d70fb24561243a930bbcc32363b (diff)
downloaduhd-1e51dd7774017cbad84315284596417636ab044d.tar.gz
uhd-1e51dd7774017cbad84315284596417636ab044d.tar.bz2
uhd-1e51dd7774017cbad84315284596417636ab044d.zip
rfnoc: radio: Add async message validation
This adds a method to the radio to check if an async message is valid, which can be used to ack async messages immediately.
-rw-r--r--host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp5
-rw-r--r--host/lib/rfnoc/radio_control_impl.cpp48
2 files changed, 53 insertions, 0 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp
index fc90035f7..5440c1e37 100644
--- a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp
+++ b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp
@@ -278,6 +278,11 @@ protected:
std::vector<property_t<double>> _samp_rate_out;
private:
+ //! Validator for the async messages
+ //
+ // We only know about overruns, underruns, and late commands/packets.
+ bool async_message_validator(uint32_t addr, const std::vector<uint32_t>& data);
+
//! Receiver for the async messages
//
// This block will receive all async messages. The following async messages
diff --git a/host/lib/rfnoc/radio_control_impl.cpp b/host/lib/rfnoc/radio_control_impl.cpp
index 9648b5dbf..2094f4096 100644
--- a/host/lib/rfnoc/radio_control_impl.cpp
+++ b/host/lib/rfnoc/radio_control_impl.cpp
@@ -250,6 +250,10 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
regmap::SWREG_RX_ERR + regmap::SWREG_CHAN_OFFSET * rx_chan);
}
// Now register a function to receive the async messages
+ regs().register_async_msg_validator(
+ [this](uint32_t addr, const std::vector<uint32_t>& data) {
+ return this->async_message_validator(addr, data);
+ });
regs().register_async_msg_handler([this](uint32_t addr,
const std::vector<uint32_t>& data,
boost::optional<uint64_t> timestamp) {
@@ -838,6 +842,50 @@ void radio_control_impl::issue_stream_cmd(
/******************************************************************************
* Private methods
*****************************************************************************/
+bool radio_control_impl::async_message_validator(
+ uint32_t addr, const std::vector<uint32_t>& data)
+{
+ if (data.empty()) {
+ return false;
+ }
+ // For these calculations, see below
+ const uint32_t addr_base = (addr >= regmap::SWREG_RX_ERR) ? regmap::SWREG_RX_ERR
+ : regmap::SWREG_TX_ERR;
+ const uint32_t chan = (addr - addr_base) / regmap::SWREG_CHAN_OFFSET;
+ const uint32_t addr_offset = addr % regmap::SWREG_CHAN_OFFSET;
+ const uint32_t code = data[0];
+ if (addr_offset > 0) {
+ return false;
+ }
+ if (addr_base == regmap::SWREG_RX_ERR) {
+ if (chan > get_num_output_ports()) {
+ return false;
+ }
+ switch (code) {
+ case err_codes::ERR_RX_OVERRUN:
+ return true;
+ case err_codes::ERR_RX_LATE_CMD:
+ return true;
+ default:
+ return false;
+ }
+ }
+ if (addr_base == regmap::SWREG_TX_ERR) {
+ if (chan > get_num_input_ports()) {
+ return false;
+ }
+ switch (code) {
+ case err_codes::ERR_TX_UNDERRUN:
+ return true;
+ case err_codes::ERR_TX_LATE_DATA:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
void radio_control_impl::async_message_handler(
uint32_t addr, const std::vector<uint32_t>& data, boost::optional<uint64_t> timestamp)
{