Hi Rob, All the blocks should get reset when you create the RFNoC graph. But the DRAM controller and related AXI4 interconnect are outside of RFNoC, so it doesn't get reset when the blocks are reset. It's possible that the DRAM logic is in a bad state as well. It doesn't look like there's a way currently to reset the DRAM logic on demand.
Does the corruption still occur after fixing the bug you mentioned? Wade On Wed, Oct 14, 2020 at 6:10 PM Rob Kossler via USRP-users < usrp-users@lists.ettus.com> wrote: > Hi, > I am using the Replay block and I ran into an issue where I have gotten > the Replay block into a bad state which I can't seem to fix short of > rebooting the N310. The way I know it is in a bad state is that the data > playing out is corrupted. Although the playout is similar to what it > should be, there are numerous gaps & drops that indicate the corruption. > If I reboot the N310, the corruption disappears. I would like to be able > to "reset" things without requiring an N310 reboot. > > My custom software controls the Replay block with 3 functions: > replay_store() and replay_play() and replay_stop(), all provided below. I > don't do anything tricky like trying to store and play simultaneously. The > replay_store() function is very similar to the > rfnoc_replay_samples_from_file() example with the exception that it doesn't > actually start or stop the playout. This occurs in my other 2 functions. > > The way that I get the replay block into a bad state is by failing to call > replay_store() prior to replay_play(). This was a bug in my software that > could occur in some situations (which I have since fixed). After this > happens, I can't produce uncorrupted playouts without rebooting the N310. > > Let me know if you have any ideas how I can "reset" the Replay block to > obtain uncorrupted output. > Rob > > > /*******************************************************/ > int nd::replay_store( > uhd::rfnoc::replay_block_control::sptr replay_ptr, > size_t port, > uhd::tx_streamer::sptr tx_stream, > std::vector<char>& samp_vec, > uint32_t addr > ){ > const std::string ID = replay_ptr->get_block_id().to_string() + ":" + > std::to_string(port); > > // Constants related to the Replay block > const size_t bytes_per_sample = 4; // Complex signed 16-bit is 32 bits per > sample > const size_t samples_per_word = 2; // Number of sc16 samples per 64-bit > word > const size_t bytes_per_word = bytes_per_sample*samples_per_word; > > size_t num_bytes = samp_vec.size(); > > // Calculate the number of 64-bit words and samples to replay > size_t words_to_replay = num_bytes / bytes_per_word; > size_t samples_to_replay = words_to_replay * samples_per_word; > uint32_t bytes_to_replay = words_to_replay * bytes_per_word; > > if (bytes_to_replay != num_bytes) { > UHD_LOGGER_WARNING(__CLASS_AND_FUNC__) << ID > << "Replay block requires an even number of samples. Truncating extra > bytes"; > } > > // Configure a buffer in the on-board memory at address 0 that's equal in > // size to the file we want to play back (rounded down to a multiple of > // 64-bit words). Note that it is allowed to playback a different size or > // location from what was recorded. > UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << > ": Configuring memory at addr 0x" << std::hex << addr << std::dec << " > for " << bytes_to_replay << " bytes"; > replay_ptr->stop(port); // just in case it is presently playing > replay_ptr->record(addr, bytes_to_replay, port); > > // Restart record buffer repeatedly until no new data appears on the Replay > // block's input. This will flush any data that was buffered on the input. > UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << ": Restarting record buffer"; > auto start_time = std::chrono::steady_clock::now(); > while (true) > { > replay_ptr->record_restart(port); > std::this_thread::sleep_for(std::chrono::milliseconds(20)); > > uint32_t fullness = replay_ptr->get_record_fullness(port); > if (fullness==0) break; > > std::chrono::duration<double> time_diff_s = > std::chrono::steady_clock::now() - start_time; > UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID > << ": Time: " << time_diff_s.count() << ": Fullness " << fullness; > > if (time_diff_s.count() > 2.0) { > UHD_LOGGER_ERROR(__CLASS_AND_FUNC__) << ID << ": Timeout waiting to flush > record buffer"; > return -1; > } > } > > > /////////////////////////////////////////////////////////////////////////// > // Send data to replay (record the data) > UHD_LOGGER_INFO(__CLASS_AND_FUNC__) << ID << ": Sending " << > samples_to_replay << " samples"; > > uhd::tx_metadata_t tx_md; > tx_md.start_of_burst = true; > tx_md.end_of_burst = true; > size_t num_tx_samps = tx_stream->send(&samp_vec[0], samples_to_replay, > tx_md); > > if (num_tx_samps != samples_to_replay) { > UHD_LOGGER_ERROR(__CLASS_AND_FUNC__) << ID << ": Error sending samples: " > << num_tx_samps << "/" << samples_to_replay; > return -1; > } > > > /////////////////////////////////////////////////////////////////////////// > // Wait for data to be stored in on-board memory > > UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << ": Waiting for recording to > complete"; > start_time = std::chrono::steady_clock::now(); > while (true) > { > uint32_t fullness = replay_ptr->get_record_fullness(port); > if (fullness>=bytes_to_replay) break; > > std::chrono::duration<double> time_diff_s = > std::chrono::steady_clock::now() - start_time; > > UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << ": Time: (s): " << > time_diff_s.count() > << ": Fullness: " << fullness << " / " << bytes_to_replay; > > if (time_diff_s.count() > 2.0) { > UHD_LOGGER_ERROR(__CLASS_AND_FUNC__) << ID << ": Timeout waiting for > recording to complete"; > return -1; > } > > std::this_thread::sleep_for(std::chrono::milliseconds(1)); > } > > UHD_LOGGER_INFO(__CLASS_AND_FUNC__) << ID << ": Successfully sent " << > samples_to_replay << " samples"; > > return samples_to_replay; > } > /*******************************************************/ > > > > /*******************************************************/ > void nd::replay_play( > uhd::rfnoc::replay_block_control::sptr replay_ptr, > size_t port, > const uhd::time_spec_t start_time > ){ > const std::string ID = replay_ptr->get_block_id().to_string() + ":" + > std::to_string(port); > uint64_t rec_addr = replay_ptr->get_record_offset(port); > uint64_t rec_size = replay_ptr->get_record_size(port); > > UHD_LOGGER_DEBUG(ID) << "Replay Started. Samples: " << (rec_size/4); > replay_ptr->play(rec_addr, rec_size, port, start_time, true); > } > /*******************************************************/ > > > > > /*******************************************************/ > void nd::replay_stop( > uhd::rfnoc::replay_block_control::sptr replay_ptr, > size_t port > ){ > const std::string ID = replay_ptr->get_block_id().to_string() + ":" + > std::to_string(port); > > UHD_LOGGER_DEBUG(ID) << "Replay Stopped"; > replay_ptr->stop(port); > } > > > _______________________________________________ > USRP-users mailing list > USRP-users@lists.ettus.com > http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com >
_______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com