mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
b310: Flush stale RX data before enabling DMA
Signed-off-by: Grant Meyerhoff <grant.meyerhoff@emerson.com>
This commit is contained in:
parent
53a1ef762e
commit
02f11f970c
@ -75,12 +75,12 @@ b300_pcie_link::b300_pcie_link(b300_pcie_session::sptr session,
|
|||||||
% _link_params.send_frame_size % _link_params.num_send_frames
|
% _link_params.send_frame_size % _link_params.num_send_frames
|
||||||
% (_link_params.send_frame_size * _link_params.num_send_frames));
|
% (_link_params.send_frame_size * _link_params.num_send_frames));
|
||||||
|
|
||||||
// --- DMA Register Configuration (like nirio_link) ---
|
// --- DMA Register Configuration ---
|
||||||
// 1. Disable DMA streams in case last shutdown was unclean
|
// 1. Disable and clear DMA streams in case last shutdown was unclean
|
||||||
_b300_session->poke32(
|
_b300_session->poke32(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
||||||
PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
|
DMA_CTRL_DISABLED | DMA_CTRL_CLEAR_STB);
|
||||||
_b300_session->poke32(
|
_b300_session->poke32(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
||||||
PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
|
DMA_CTRL_DISABLED | DMA_CTRL_CLEAR_STB);
|
||||||
|
|
||||||
_wait_until_stream_ready();
|
_wait_until_stream_ready();
|
||||||
|
|
||||||
@ -93,12 +93,6 @@ b300_pcie_link::b300_pcie_link(b300_pcie_session::sptr session,
|
|||||||
static_cast<uint32_t>(_link_params.recv_frame_size / chdr_word_size));
|
static_cast<uint32_t>(_link_params.recv_frame_size / chdr_word_size));
|
||||||
|
|
||||||
|
|
||||||
// 3. Configure 64-bit word flipping and enable DMA streams
|
|
||||||
_b300_session->poke32(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
|
||||||
DMA_CTRL_SW_BUF_U64 | DMA_CTRL_ENABLED);
|
|
||||||
_b300_session->poke32(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
|
||||||
DMA_CTRL_SW_BUF_U64 | DMA_CTRL_ENABLED);
|
|
||||||
|
|
||||||
// Create FIFOs
|
// Create FIFOs
|
||||||
_recv_fifo = _b300_session->create_rx_fifo(_fifo_instance);
|
_recv_fifo = _b300_session->create_rx_fifo(_fifo_instance);
|
||||||
_send_fifo = _b300_session->create_tx_fifo(_fifo_instance + B300_TX_FIFO_OFFSET);
|
_send_fifo = _b300_session->create_tx_fifo(_fifo_instance + B300_TX_FIFO_OFFSET);
|
||||||
@ -117,6 +111,15 @@ b300_pcie_link::b300_pcie_link(b300_pcie_session::sptr session,
|
|||||||
// Start FIFOs
|
// Start FIFOs
|
||||||
_recv_fifo->start();
|
_recv_fifo->start();
|
||||||
_send_fifo->start();
|
_send_fifo->start();
|
||||||
|
|
||||||
|
// Flush stale RX data before enabling the DMA streams.
|
||||||
|
UHD_SAFE_CALL(_flush_rx_buff());
|
||||||
|
|
||||||
|
// 3. Configure 64-bit word flipping and enable DMA streams
|
||||||
|
_b300_session->poke32(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
||||||
|
DMA_CTRL_SW_BUF_U64 | DMA_CTRL_ENABLED);
|
||||||
|
_b300_session->poke32(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
||||||
|
DMA_CTRL_SW_BUF_U64 | DMA_CTRL_ENABLED);
|
||||||
} else {
|
} else {
|
||||||
throw uhd::runtime_error("Could not create B300 PCIe link!");
|
throw uhd::runtime_error("Could not create B300 PCIe link!");
|
||||||
}
|
}
|
||||||
@ -151,11 +154,11 @@ b300_pcie_link::~b300_pcie_link()
|
|||||||
_release_cb(_fifo_instance);
|
_release_cb(_fifo_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Disable DMA streams (like nirio_link) ---
|
// --- Disable and clear DMA streams during link cleanup ---
|
||||||
_b300_session->poke32(
|
_b300_session->poke32(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
||||||
PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
|
DMA_CTRL_DISABLED | DMA_CTRL_CLEAR_STB);
|
||||||
_b300_session->poke32(
|
_b300_session->poke32(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
|
||||||
PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
|
DMA_CTRL_DISABLED | DMA_CTRL_CLEAR_STB);
|
||||||
|
|
||||||
// Flush any pending buffers
|
// Flush any pending buffers
|
||||||
UHD_SAFE_CALL(_flush_rx_buff());
|
UHD_SAFE_CALL(_flush_rx_buff());
|
||||||
@ -384,25 +387,48 @@ adapter_id_t b300_pcie_link::get_recv_adapter_id() const
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
void b300_pcie_link::_flush_rx_buff()
|
void b300_pcie_link::_flush_rx_buff()
|
||||||
{
|
{
|
||||||
// Acquire is called with 0 elements requested first to
|
// Poll the RX FIFO until it has remained empty for a quiet period.
|
||||||
// get the number of elements in the buffer and then
|
constexpr auto quiet_poll_interval = std::chrono::milliseconds(1);
|
||||||
// repeatedly with the number of remaining elements
|
constexpr auto quiet_period = std::chrono::milliseconds(20);
|
||||||
// until the buffer is empty
|
constexpr auto flush_timeout = std::chrono::milliseconds(1000);
|
||||||
for (size_t num_elems_requested = 0, num_elems_remaining = 1; num_elems_remaining;
|
|
||||||
num_elems_requested = num_elems_remaining) {
|
size_t num_elems_remaining = 0;
|
||||||
uint64_t* elems_buffer = nullptr;
|
const auto flush_deadline = std::chrono::steady_clock::now() + flush_timeout;
|
||||||
|
auto quiet_deadline = std::chrono::steady_clock::time_point{};
|
||||||
|
bool quiet_period_started = false;
|
||||||
|
|
||||||
|
while (std::chrono::steady_clock::now() < flush_deadline) {
|
||||||
|
const size_t num_elems_requested = num_elems_remaining;
|
||||||
|
uint64_t* elems_buffer = nullptr;
|
||||||
try {
|
try {
|
||||||
auto result = _recv_fifo->acquire(elems_buffer,
|
auto result = _recv_fifo->acquire(elems_buffer,
|
||||||
num_elems_requested,
|
num_elems_requested,
|
||||||
0); // timeout
|
0); // timeout
|
||||||
num_elems_remaining = result.elements_remaining;
|
num_elems_remaining = result.elements_remaining;
|
||||||
_recv_fifo->release(result.elements_acquired);
|
_recv_fifo->release(result.elements_acquired);
|
||||||
|
|
||||||
|
if (num_elems_remaining) {
|
||||||
|
quiet_period_started = false;
|
||||||
|
} else {
|
||||||
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
if (!quiet_period_started) {
|
||||||
|
quiet_deadline = now + quiet_period;
|
||||||
|
quiet_period_started = true;
|
||||||
|
} else if (now >= quiet_deadline) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(quiet_poll_interval);
|
||||||
|
}
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
UHD_LOG_WARNING(
|
UHD_LOG_WARNING(
|
||||||
"B300", "B300 PCIe data transfer failed during flush: " << ex.what());
|
"B300", "B300 PCIe data transfer failed during flush: " << ex.what());
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UHD_LOG_WARNING("B300",
|
||||||
|
"Timed out flushing RX FIFO for channel " << _fifo_instance << " after "
|
||||||
|
<< flush_timeout.count() << " ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
void b300_pcie_link::_wait_until_stream_ready()
|
void b300_pcie_link::_wait_until_stream_ready()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user