diff options
Diffstat (limited to 'host/lib')
-rw-r--r-- | host/lib/rfnoc/ctrlport_endpoint.cpp | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/host/lib/rfnoc/ctrlport_endpoint.cpp b/host/lib/rfnoc/ctrlport_endpoint.cpp index c544a3d4e..2078ecce1 100644 --- a/host/lib/rfnoc/ctrlport_endpoint.cpp +++ b/host/lib/rfnoc/ctrlport_endpoint.cpp @@ -10,7 +10,7 @@ #include <uhdlib/rfnoc/chdr_packet_writer.hpp> #include <uhdlib/rfnoc/ctrlport_endpoint.hpp> #include <condition_variable> -#include <boost/format.hpp> +#include <boost/optional.hpp> #include <deque> #include <mutex> #include <numeric> @@ -67,9 +67,8 @@ public: // Send request auto request = send_request_packet(OP_WRITE, addr, {data}, timestamp); // Optionally wait for an ACK - if (ack || _policy.force_acks) { - wait_for_ack(request); - } + const bool require_ack = ack || _policy.force_acks; + wait_for_ack(request, require_ack); } void multi_poke32(const std::vector<uint32_t> addrs, @@ -104,9 +103,8 @@ public: // Send request auto request = send_request_packet(OP_BLOCK_WRITE, first_addr, data, timestamp); // Optionally wait for an ACK - if (ack || _policy.force_acks) { - wait_for_ack(request); - } + const bool require_ack = ack || _policy.force_acks; + wait_for_ack(request, require_ack); */ } @@ -117,7 +115,7 @@ public: auto request = send_request_packet(OP_READ, addr, {uint32_t(0)}, timestamp); // Wait for an ACK - auto response = wait_for_ack(request); + auto response = wait_for_ack(request, true).get(); return response.data_vtr[0]; } @@ -140,7 +138,7 @@ public: timestamp); // Wait for an ACK - auto response = wait_for_ack(request); + auto response = wait_for_ack(request, true).get(); return response.data_vtr; */ } @@ -164,9 +162,8 @@ public: timestamp); // Optionally wait for an ACK - if (ack || _policy.force_acks) { - wait_for_ack(request); - } + const bool require_ack = ack || _policy.force_acks; + wait_for_ack(request, require_ack); } void sleep(uhd::time_spec_t duration, bool ack = false) override @@ -178,9 +175,8 @@ public: uhd::time_spec_t::ASAP); // Optionally wait for an ACK - if (ack || _policy.force_acks) { - wait_for_ack(request); - } + const bool require_ack = ack || _policy.force_acks; + wait_for_ack(request, require_ack); } void register_async_msg_validator(async_msg_validator_t callback_f) override @@ -415,13 +411,30 @@ private: } //! Waits for and returns the ACK for the specified request - const ctrl_payload wait_for_ack(const ctrl_payload& request) + // + // \param request The request for which we are awaiting the response + // \param require_ack A Boolean flag which indicates if we really need that + // response. If false, we reduce the timeout to zero + // and return an empty control payload if we can't find + // the relevant ACK. This can be used to help clear the + // response queue without waiting. + // \returns The response payload corresponding to \p requst. If \p require_ack + // is false, this may also be an empty ctrl_payload object with no + // meaningful content. + // \throws uhd::op_timeout if require_ack is true, and we exceed the timeout + // set by the current policy. Throws various other uhd::rfnoc_error + // when there was a communication issue (see the code for details). + const boost::optional<ctrl_payload> wait_for_ack( + const ctrl_payload& request, const bool require_ack) { auto resp_ready = [this]() -> bool { return !_resp_queue.empty(); }; while (true) { std::unique_lock<std::mutex> lock(_mutex); // Wait until there is a response in the response queue if (!resp_ready()) { + if (!require_ack) { + return {}; + } // If we're waiting for a timed command or if we have a // command in the queue, use the MASSIVE_TIMEOUT instead auto timeout_time = start_timeout( |