mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 12:10:34 +00:00
Merge branch 'mmajoral-buffer_monitor' into next
This commit is contained in:
commit
de4dfd410c
@ -98,22 +98,24 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
|
|||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_position = configuration->property(role + ".switch_position", 0);
|
switch_position_ = configuration->property(role + ".switch_position", 0);
|
||||||
if (switch_position != 0 && switch_position != 2)
|
if (switch_position_ != 0 && switch_position_ != 2)
|
||||||
{
|
{
|
||||||
std::cout << "SignalSource.switch_position configuration parameter must be either 0: read from file(s) via DMA, or 2: read from AD9361\n";
|
std::cout << "SignalSource.switch_position configuration parameter must be either 0: read from file(s) via DMA, or 2: read from AD9361\n";
|
||||||
std::cout << "SignalSource.switch_position configuration parameter set to its default value switch_position=0 - read from file(s)\n";
|
std::cout << "SignalSource.switch_position configuration parameter set to its default value switch_position=0 - read from file(s)\n";
|
||||||
switch_position = 0;
|
switch_position_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
|
switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
|
||||||
switch_fpga->set_switch_position(switch_position);
|
switch_fpga->set_switch_position(switch_position_);
|
||||||
|
|
||||||
item_size_ = sizeof(gr_complex);
|
item_size_ = sizeof(gr_complex);
|
||||||
|
|
||||||
std::cout << "Sample rate: " << sample_rate_ << " Sps\n";
|
std::cout << "Sample rate: " << sample_rate_ << " Sps\n";
|
||||||
|
|
||||||
if (switch_position == 0) // Inject file(s) via DMA
|
enable_ovf_check_buffer_monitor_active_ = false; // check buffer overflow and buffer monitor disabled by default
|
||||||
|
|
||||||
|
if (switch_position_ == 0) // Inject file(s) via DMA
|
||||||
{
|
{
|
||||||
enable_DMA_ = true;
|
enable_DMA_ = true;
|
||||||
const std::string empty_string;
|
const std::string empty_string;
|
||||||
@ -154,7 +156,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
|
|||||||
freq_band = "L1L2";
|
freq_band = "L1L2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (switch_position == 2) // Real-time via AD9361
|
if (switch_position_ == 2) // Real-time via AD9361
|
||||||
{
|
{
|
||||||
// some basic checks
|
// some basic checks
|
||||||
if ((rf_port_select_ != "A_BALANCED") and (rf_port_select_ != "B_BALANCED") and (rf_port_select_ != "A_N") and (rf_port_select_ != "B_N") and (rf_port_select_ != "B_P") and (rf_port_select_ != "C_N") and (rf_port_select_ != "C_P") and (rf_port_select_ != "TX_MONITOR1") and (rf_port_select_ != "TX_MONITOR2") and (rf_port_select_ != "TX_MONITOR1_2"))
|
if ((rf_port_select_ != "A_BALANCED") and (rf_port_select_ != "B_BALANCED") and (rf_port_select_ != "A_N") and (rf_port_select_ != "B_N") and (rf_port_select_ != "B_P") and (rf_port_select_ != "C_N") and (rf_port_select_ != "C_P") and (rf_port_select_ != "TX_MONITOR1") and (rf_port_select_ != "TX_MONITOR2") and (rf_port_select_ != "TX_MONITOR1_2"))
|
||||||
@ -292,6 +294,26 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
|
|||||||
std::cout << "Exception cached when configuring the TX carrier: " << e.what() << '\n';
|
std::cout << "Exception cached when configuring the TX carrier: " << e.what() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when the receiver is working in real-time mode via AD9361 perform buffer overflow checking,
|
||||||
|
// and if dump is enabled perform buffer monitoring
|
||||||
|
enable_ovf_check_buffer_monitor_active_ = true;
|
||||||
|
|
||||||
|
std::string device_io_name_buffer_monitor;
|
||||||
|
|
||||||
|
dump_ = configuration->property(role + ".dump", false);
|
||||||
|
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||||
|
|
||||||
|
// find the uio device file corresponding to the buffer monitor
|
||||||
|
if (find_uio_dev_file_name(device_io_name_buffer_monitor, buffer_monitor_device_name, 0) < 0)
|
||||||
|
{
|
||||||
|
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << buffer_monitor_device_name << std::endl;
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t num_freq_bands = (freq_band.compare("L1L2")) ? 1 : 2;
|
||||||
|
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(device_io_name_buffer_monitor, num_freq_bands, dump_, dump_filename, queue);
|
||||||
|
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// dynamic bits selection
|
// dynamic bits selection
|
||||||
@ -331,7 +353,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
|
|||||||
Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
|
Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
|
||||||
{
|
{
|
||||||
/* cleanup and exit */
|
/* cleanup and exit */
|
||||||
if (switch_position == 0) // read samples from a file via DMA
|
if (switch_position_ == 0) // read samples from a file via DMA
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(dma_mutex);
|
std::unique_lock<std::mutex> lock(dma_mutex);
|
||||||
enable_DMA_ = false; // disable the DMA
|
enable_DMA_ = false; // disable the DMA
|
||||||
@ -342,7 +364,7 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_position == 2) // Real-time via AD9361
|
if (switch_position_ == 2) // Real-time via AD9361
|
||||||
{
|
{
|
||||||
if (rf_shutdown_)
|
if (rf_shutdown_)
|
||||||
{
|
{
|
||||||
@ -363,6 +385,16 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// disable buffer overflow checking and buffer monitoring
|
||||||
|
std::unique_lock<std::mutex> lock(buffer_monitor_mutex);
|
||||||
|
enable_ovf_check_buffer_monitor_active_ = false;
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
if (thread_buffer_monitor.joinable())
|
||||||
|
{
|
||||||
|
thread_buffer_monitor.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
|
std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
|
||||||
@ -646,6 +678,25 @@ void Ad9361FpgaSignalSource::run_dynamic_bit_selection_process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ad9361FpgaSignalSource::run_buffer_monitor_process()
|
||||||
|
{
|
||||||
|
bool enable_ovf_check_buffer_monitor_active = true;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitoring_initial_delay_ms));
|
||||||
|
|
||||||
|
while (enable_ovf_check_buffer_monitor_active)
|
||||||
|
{
|
||||||
|
buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms));
|
||||||
|
std::unique_lock<std::mutex> lock(buffer_monitor_mutex);
|
||||||
|
if (enable_ovf_check_buffer_monitor_active_ == false)
|
||||||
|
{
|
||||||
|
enable_ovf_check_buffer_monitor_active = false;
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Ad9361FpgaSignalSource::connect(gr::top_block_sptr top_block)
|
void Ad9361FpgaSignalSource::connect(gr::top_block_sptr top_block)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H
|
#define GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
|
#include "fpga_buffer_monitor.h"
|
||||||
#include "fpga_dynamic_bit_selection.h"
|
#include "fpga_dynamic_bit_selection.h"
|
||||||
#include "fpga_switch.h"
|
#include "fpga_switch.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "gnss_block_interface.h"
|
||||||
@ -74,22 +75,30 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string switch_device_name = "AXIS_Switch_v1_0_0"; // Switch UIO device name
|
const std::string switch_device_name = "AXIS_Switch_v1_0_0"; // Switch UIO device name
|
||||||
const std::string dyn_bit_sel_device_name = "dynamic_bits_selector"; // Switch UIO device name
|
const std::string dyn_bit_sel_device_name = "dynamic_bits_selector"; // Switch dhnamic bit selector device name
|
||||||
|
const std::string buffer_monitor_device_name = "buffer_monitor"; // buffer monitor device name
|
||||||
|
const std::string default_dump_filename = std::string("FPGA_buffer_monitor_dump.dat");
|
||||||
// perform dynamic bit selection every 500 ms by default
|
// perform dynamic bit selection every 500 ms by default
|
||||||
static const uint32_t Gain_control_period_ms = 500;
|
static const uint32_t Gain_control_period_ms = 500;
|
||||||
|
// check buffer overflow and perform buffer monitoring every 1s by default
|
||||||
|
static const uint32_t buffer_monitor_period_ms = 1000;
|
||||||
|
// buffer overflow and buffer monitoring initial delay
|
||||||
|
static const uint32_t buffer_monitoring_initial_delay_ms = 2000;
|
||||||
|
|
||||||
void run_DMA_process(const std::string &FreqBand,
|
void run_DMA_process(const std::string &FreqBand,
|
||||||
const std::string &Filename1,
|
const std::string &Filename1,
|
||||||
const std::string &Filename2);
|
const std::string &Filename2);
|
||||||
|
|
||||||
void run_dynamic_bit_selection_process();
|
void run_dynamic_bit_selection_process();
|
||||||
|
void run_buffer_monitor_process();
|
||||||
|
|
||||||
std::thread thread_file_to_dma;
|
std::thread thread_file_to_dma;
|
||||||
std::thread thread_dynamic_bit_selection;
|
std::thread thread_dynamic_bit_selection;
|
||||||
|
std::thread thread_buffer_monitor;
|
||||||
|
|
||||||
std::shared_ptr<Fpga_Switch> switch_fpga;
|
std::shared_ptr<Fpga_Switch> switch_fpga;
|
||||||
std::shared_ptr<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
|
std::shared_ptr<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
|
||||||
|
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
|
||||||
|
|
||||||
std::string role_;
|
std::string role_;
|
||||||
|
|
||||||
@ -106,6 +115,7 @@ private:
|
|||||||
|
|
||||||
std::mutex dma_mutex;
|
std::mutex dma_mutex;
|
||||||
std::mutex dynamic_bit_selection_mutex;
|
std::mutex dynamic_bit_selection_mutex;
|
||||||
|
std::mutex buffer_monitor_mutex;
|
||||||
|
|
||||||
double rf_gain_rx1_;
|
double rf_gain_rx1_;
|
||||||
double rf_gain_rx2_;
|
double rf_gain_rx2_;
|
||||||
@ -125,7 +135,7 @@ private:
|
|||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
uint32_t in_stream_;
|
uint32_t in_stream_;
|
||||||
uint32_t out_stream_;
|
uint32_t out_stream_;
|
||||||
int32_t switch_position;
|
int32_t switch_position_;
|
||||||
bool enable_dds_lo_;
|
bool enable_dds_lo_;
|
||||||
|
|
||||||
bool filter_auto_;
|
bool filter_auto_;
|
||||||
@ -136,6 +146,9 @@ private:
|
|||||||
bool rx2_enable_;
|
bool rx2_enable_;
|
||||||
bool enable_DMA_;
|
bool enable_DMA_;
|
||||||
bool enable_dynamic_bit_selection_;
|
bool enable_dynamic_bit_selection_;
|
||||||
|
bool enable_ovf_check_buffer_monitor_active_;
|
||||||
|
bool enable_ovf_check_buffer_monitor_;
|
||||||
|
bool dump_;
|
||||||
bool rf_shutdown_;
|
bool rf_shutdown_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ if(ENABLE_FPGA OR ENABLE_AD9361)
|
|||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_switch.h)
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_switch.h)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dynamic_bit_selection.cc)
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dynamic_bit_selection.cc)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dynamic_bit_selection.h)
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dynamic_bit_selection.h)
|
||||||
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_buffer_monitor.cc)
|
||||||
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_buffer_monitor.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SIGNAL_SOURCE_LIB_SOURCES
|
set(SIGNAL_SOURCE_LIB_SOURCES
|
||||||
@ -90,6 +92,13 @@ if(ENABLE_FMCOMMS2 OR ENABLE_AD9361)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_FPGA OR ENABLE_AD9361)
|
||||||
|
target_link_libraries(signal_source_libs
|
||||||
|
PUBLIC
|
||||||
|
algorithms_libs
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_CLANG_TIDY)
|
if(ENABLE_CLANG_TIDY)
|
||||||
if(CLANG_TIDY_EXE)
|
if(CLANG_TIDY_EXE)
|
||||||
set_target_properties(signal_source_libs
|
set_target_properties(signal_source_libs
|
||||||
|
260
src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
Normal file
260
src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/*!
|
||||||
|
* \file fpga_buffer_monitor.cc
|
||||||
|
* \brief Check receiver buffer overflow and monitor the status of the receiver
|
||||||
|
* buffers.
|
||||||
|
* \authors
|
||||||
|
* <ul>
|
||||||
|
* <li> Marc Majoral, 2021. mmajoral(at)cttc.es
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Class that checks the receiver buffer overflow flags and monitors the status
|
||||||
|
* of the receiver buffers.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fpga_buffer_monitor.h"
|
||||||
|
#include "command_event.h"
|
||||||
|
#include "gnss_sdr_create_directory.h"
|
||||||
|
#include "gnss_sdr_filesystem.h"
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include <ctime> // for time, localtime
|
||||||
|
#include <fcntl.h> // for open, O_RDWR, O_SYNC
|
||||||
|
#include <fstream> // for string, ofstream
|
||||||
|
#include <iostream> // for cout
|
||||||
|
#include <sys/mman.h> // for mmap
|
||||||
|
|
||||||
|
Fpga_buffer_monitor::Fpga_buffer_monitor(const std::string &device_name, uint32_t num_freq_bands, bool dump, std::string dump_filename, Concurrent_Queue<pmt::pmt_t> *queue)
|
||||||
|
{
|
||||||
|
d_num_freq_bands = num_freq_bands;
|
||||||
|
d_dump = dump;
|
||||||
|
d_dump_filename = dump_filename;
|
||||||
|
d_queue = queue;
|
||||||
|
|
||||||
|
// open device descriptor
|
||||||
|
if ((d_device_descriptor = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Cannot open deviceio" << device_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// device memory map
|
||||||
|
d_map_base = reinterpret_cast<volatile unsigned *>(mmap(nullptr, FPGA_PAGE_SIZE,
|
||||||
|
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0));
|
||||||
|
|
||||||
|
if (d_map_base == reinterpret_cast<void *>(-1))
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Cannot map the FPGA buffer monitor module";
|
||||||
|
std::cout << "Could not map the FPGA buffer monitor \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check: check test register
|
||||||
|
if (buffer_monitor_test_register() < 0)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "FPGA buffer monitor test register sanity check failed";
|
||||||
|
std::cout << "FPGA buffer monitor test register sanity check failed\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(INFO) << "FPGA buffer monitor test register sanity check success !";
|
||||||
|
}
|
||||||
|
|
||||||
|
DLOG(INFO) << "FPGA buffer monitor class created";
|
||||||
|
|
||||||
|
// initialize maximum buffer occupancy in case buffer monitoring is enabled
|
||||||
|
d_max_buff_occ_freq_band_0 = 0;
|
||||||
|
d_max_buff_occ_freq_band_1 = 0;
|
||||||
|
|
||||||
|
if (d_dump)
|
||||||
|
{
|
||||||
|
std::string dump_path;
|
||||||
|
// Get path
|
||||||
|
if (d_dump_filename.find_last_of('/') != std::string::npos)
|
||||||
|
{
|
||||||
|
const std::string dump_filename_ = d_dump_filename.substr(d_dump_filename.find_last_of('/') + 1);
|
||||||
|
dump_path = d_dump_filename.substr(0, d_dump_filename.find_last_of('/'));
|
||||||
|
d_dump_filename = dump_filename_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dump_path = std::string(".");
|
||||||
|
}
|
||||||
|
if (d_dump_filename.empty())
|
||||||
|
{
|
||||||
|
d_dump_filename = "FPGA_buffer_monitor";
|
||||||
|
}
|
||||||
|
// remove extension if any
|
||||||
|
if (d_dump_filename.substr(1).find_last_of('.') != std::string::npos)
|
||||||
|
{
|
||||||
|
d_dump_filename = d_dump_filename.substr(0, d_dump_filename.find_last_of('.'));
|
||||||
|
}
|
||||||
|
d_dump_filename = dump_path + fs::path::preferred_separator + d_dump_filename;
|
||||||
|
// create directory
|
||||||
|
if (!gnss_sdr_create_directory(dump_path))
|
||||||
|
{
|
||||||
|
std::cerr << "GNSS-SDR cannot create dump file for the Buffer Monitor block. Wrong permissions?\n";
|
||||||
|
d_dump = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dump_filename_ = d_dump_filename;
|
||||||
|
dump_filename_.append(".dat");
|
||||||
|
|
||||||
|
if (!d_dump_file.is_open())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
|
d_dump_file.open(dump_filename_.c_str(), std::ios::out | std::ios::binary);
|
||||||
|
LOG(INFO) << "FPGA buffer monitor dump enabled. Log file: " << dump_filename_.c_str();
|
||||||
|
}
|
||||||
|
catch (const std::ifstream::failure &e)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Exception opening FPGA buffer monitor dump file " << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Fpga_buffer_monitor::~Fpga_buffer_monitor()
|
||||||
|
{
|
||||||
|
close_device();
|
||||||
|
|
||||||
|
if (d_dump)
|
||||||
|
{
|
||||||
|
if (d_dump_file.is_open())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d_dump_file.close();
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Exception in FPGA buffer monitor destructor: " << ex.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Fpga_buffer_monitor::check_buffer_overflow_and_monitor_buffer_status(void)
|
||||||
|
{
|
||||||
|
// check buffer overflow flags
|
||||||
|
bool overflow_detected = false;
|
||||||
|
uint32_t buffer_overflow_status = d_map_base[overflow_flags_reg_addr];
|
||||||
|
|
||||||
|
if ((buffer_overflow_status & overflow_freq_band_0_bit_pos) != 0)
|
||||||
|
{
|
||||||
|
overflow_detected = true;
|
||||||
|
std::cout << "Buffer overflow in frequency band 0" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d_num_freq_bands > 1)
|
||||||
|
{
|
||||||
|
if ((buffer_overflow_status & overflow_freq_band_1_bit_pos) != 0)
|
||||||
|
{
|
||||||
|
overflow_detected = true;
|
||||||
|
std::cout << "Buffer overflow in frequency band 1" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overflow_detected)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Stopping receiver, FPGA buffer overflow detected.";
|
||||||
|
d_queue->push(pmt::make_any(command_event_make(200, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffer monitor
|
||||||
|
if (d_dump == 1)
|
||||||
|
{
|
||||||
|
uint32_t current_buff_occ_freq_band_0 = d_map_base[current_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element;
|
||||||
|
uint32_t temp_max_buff_occ_freq_band_0 = d_map_base[max_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element;
|
||||||
|
if (temp_max_buff_occ_freq_band_0 > d_max_buff_occ_freq_band_0)
|
||||||
|
{
|
||||||
|
d_max_buff_occ_freq_band_0 = temp_max_buff_occ_freq_band_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm *timeinfo;
|
||||||
|
char buff_time_ch[80];
|
||||||
|
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
|
strftime(buff_time_ch, sizeof(buff_time_ch), "%d-%m-%Y %H:%M:%S", timeinfo);
|
||||||
|
std::string buffer_time(buff_time_ch);
|
||||||
|
d_dump_file << buffer_time << " ";
|
||||||
|
|
||||||
|
std::string buffer_txt;
|
||||||
|
// current buffer occupancy frequency band 0 (number of samples)
|
||||||
|
buffer_txt = std::to_string(current_buff_occ_freq_band_0);
|
||||||
|
d_dump_file << buffer_txt << " ";
|
||||||
|
// temporary maximum buffer occupancy frequency band 0 (number of samples)
|
||||||
|
buffer_txt = std::to_string(temp_max_buff_occ_freq_band_0);
|
||||||
|
d_dump_file << buffer_txt << " ";
|
||||||
|
// maximum buffer occupancy frequency band 0 (number of samples)
|
||||||
|
buffer_txt = std::to_string(d_max_buff_occ_freq_band_0);
|
||||||
|
d_dump_file << buffer_txt;
|
||||||
|
|
||||||
|
if (d_num_freq_bands > 1)
|
||||||
|
{
|
||||||
|
d_dump_file << " ";
|
||||||
|
uint32_t current_buff_occ_freq_band_1 = d_map_base[current_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element;
|
||||||
|
uint32_t temp_max_buff_occ_freq_band_1 = d_map_base[max_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element;
|
||||||
|
if (temp_max_buff_occ_freq_band_1 > d_max_buff_occ_freq_band_1)
|
||||||
|
{
|
||||||
|
d_max_buff_occ_freq_band_1 = temp_max_buff_occ_freq_band_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// current buffer occupancy frequency band 1 (number of samples)
|
||||||
|
buffer_txt = std::to_string(current_buff_occ_freq_band_1);
|
||||||
|
d_dump_file << buffer_txt << " ";
|
||||||
|
// temporary maximum buffer occupancy frequency band 1 (number of samples)
|
||||||
|
buffer_txt = std::to_string(temp_max_buff_occ_freq_band_1);
|
||||||
|
d_dump_file << buffer_txt << " ";
|
||||||
|
// maximum buffer occupancy frequency band 1 (number of samples)
|
||||||
|
buffer_txt = std::to_string(d_max_buff_occ_freq_band_1);
|
||||||
|
d_dump_file << buffer_txt << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_dump_file << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t Fpga_buffer_monitor::buffer_monitor_test_register(void)
|
||||||
|
{
|
||||||
|
// write value to test register
|
||||||
|
d_map_base[test_reg_addr] = test_register_writeval;
|
||||||
|
// read value from test register
|
||||||
|
uint32_t readval = d_map_base[test_reg_addr];
|
||||||
|
|
||||||
|
if (test_register_writeval != readval)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Fpga_buffer_monitor::close_device()
|
||||||
|
{
|
||||||
|
auto *aux = const_cast<unsigned *>(d_map_base);
|
||||||
|
if (munmap(static_cast<void *>(aux), FPGA_PAGE_SIZE) == -1)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to unmap memory uio\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
close(d_device_descriptor);
|
||||||
|
}
|
104
src/algorithms/signal_source/libs/fpga_buffer_monitor.h
Normal file
104
src/algorithms/signal_source/libs/fpga_buffer_monitor.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*!
|
||||||
|
* \file fpga_buffer_monitor.h
|
||||||
|
* \brief Check receiver buffer overflow and monitor the status of the receiver
|
||||||
|
* buffers.
|
||||||
|
* \authors
|
||||||
|
* <ul>
|
||||||
|
* <li> Marc Majoral, 2021. mmajoral(at)cttc.es
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Class that checks the receiver buffer overflow flags and monitors the status
|
||||||
|
* of the receiver buffers.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_FPGA_BUFFER_MONITOR_H
|
||||||
|
#define GNSS_SDR_FPGA_BUFFER_MONITOR_H
|
||||||
|
|
||||||
|
#include "concurrent_queue.h"
|
||||||
|
#include <pmt/pmt.h> // pmt
|
||||||
|
#include <cstdint> // for int32_t
|
||||||
|
#include <fstream> // for string, ofstream
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_libs
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Class that checks the receiver buffer overflow flags and monitors the
|
||||||
|
* status of the receiver buffers.
|
||||||
|
*/
|
||||||
|
class Fpga_buffer_monitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief Constructor
|
||||||
|
*/
|
||||||
|
explicit Fpga_buffer_monitor(const std::string& device_name,
|
||||||
|
uint32_t num_freq_bands,
|
||||||
|
bool dump,
|
||||||
|
std::string dump_filename,
|
||||||
|
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Destructor
|
||||||
|
*/
|
||||||
|
~Fpga_buffer_monitor();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief This function checks buffer overflow and monitors the FPGA buffer status
|
||||||
|
*/
|
||||||
|
void check_buffer_overflow_and_monitor_buffer_status(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t FPGA_PAGE_SIZE = 0x10000;
|
||||||
|
static const uint32_t test_register_writeval = 0x55AA;
|
||||||
|
static const uint32_t num_sapmples_per_buffer_element = 2;
|
||||||
|
// write addresses
|
||||||
|
static const uint32_t reset_overflow_flags_and_max_buff_size_reg_addr = 0;
|
||||||
|
// read-write addresses
|
||||||
|
static const uint32_t test_reg_addr = 7;
|
||||||
|
// read addresses
|
||||||
|
static const uint32_t current_buff_occ_freq_band_0_reg_addr = 0;
|
||||||
|
static const uint32_t current_buff_occ_freq_band_1_reg_addr = 1;
|
||||||
|
static const uint32_t max_buff_occ_freq_band_0_reg_addr = 2;
|
||||||
|
static const uint32_t max_buff_occ_freq_band_1_reg_addr = 3;
|
||||||
|
static const uint32_t overflow_flags_reg_addr = 4;
|
||||||
|
// FPGA-related constants
|
||||||
|
static const uint32_t overflow_freq_band_0_bit_pos = 1;
|
||||||
|
static const uint32_t overflow_freq_band_1_bit_pos = 2;
|
||||||
|
|
||||||
|
int32_t buffer_monitor_test_register(void);
|
||||||
|
void close_device(void);
|
||||||
|
|
||||||
|
volatile unsigned* d_map_base; // driver memory map corresponding to the FPGA buffer monitor
|
||||||
|
int d_device_descriptor; // driver descriptor corresponding to the FPGA buffer monitor
|
||||||
|
|
||||||
|
uint32_t d_num_freq_bands;
|
||||||
|
|
||||||
|
uint32_t d_max_buff_occ_freq_band_0;
|
||||||
|
uint32_t d_max_buff_occ_freq_band_1;
|
||||||
|
|
||||||
|
bool d_dump;
|
||||||
|
std::string d_dump_filename;
|
||||||
|
std::ofstream d_dump_file;
|
||||||
|
|
||||||
|
Concurrent_Queue<pmt::pmt_t>* d_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
#endif // GNSS_SDR_FPGA_BUFFER_MONITOR_H
|
Loading…
Reference in New Issue
Block a user