1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-11-19 00:04:58 +00:00

Merge branch 'mmajoral-DMA' into next

This commit is contained in:
Carles Fernandez 2022-12-05 21:25:55 +01:00
commit 2ba268fd1a
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
15 changed files with 187 additions and 113 deletions

View File

@ -197,7 +197,6 @@ private:
volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts
std::weak_ptr<ChannelFsm> channel_fsm_; std::weak_ptr<ChannelFsm> channel_fsm_;
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
const ConfigurationInterface* configuration_;
Acq_Conf_Fpga acq_parameters_; Acq_Conf_Fpga acq_parameters_;
std::string role_; std::string role_;
int64_t fs_in_; int64_t fs_in_;

View File

@ -204,7 +204,6 @@ private:
std::weak_ptr<ChannelFsm> channel_fsm_; std::weak_ptr<ChannelFsm> channel_fsm_;
volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
const ConfigurationInterface* configuration_;
Acq_Conf_Fpga acq_parameters_; Acq_Conf_Fpga acq_parameters_;
std::string role_; std::string role_;
int64_t fs_in_; int64_t fs_in_;

View File

@ -204,7 +204,6 @@ private:
std::weak_ptr<ChannelFsm> channel_fsm_; std::weak_ptr<ChannelFsm> channel_fsm_;
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
const ConfigurationInterface* configuration_;
Acq_Conf_Fpga acq_parameters_; Acq_Conf_Fpga acq_parameters_;
std::string role_; std::string role_;
int64_t fs_in_; int64_t fs_in_;

View File

@ -202,7 +202,6 @@ private:
std::weak_ptr<ChannelFsm> channel_fsm_; std::weak_ptr<ChannelFsm> channel_fsm_;
volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
const ConfigurationInterface* configuration_;
Acq_Conf_Fpga acq_parameters_; Acq_Conf_Fpga acq_parameters_;
std::string role_; std::string role_;
int64_t fs_in_; int64_t fs_in_;

View File

@ -22,7 +22,6 @@
#include "configuration_interface.h" #include "configuration_interface.h"
#include "gnss_sdr_fft.h" #include "gnss_sdr_fft.h"
#include "gnss_sdr_flags.h" #include "gnss_sdr_flags.h"
#include "gnss_synchro.h"
#include "gps_l2c_signal_replica.h" #include "gps_l2c_signal_replica.h"
#include <glog/logging.h> #include <glog/logging.h>
#include <gnuradio/gr_complex.h> // for gr_complex #include <gnuradio/gr_complex.h> // for gr_complex

View File

@ -22,6 +22,7 @@
#include "acq_conf_fpga.h" #include "acq_conf_fpga.h"
#include "channel_fsm.h" #include "channel_fsm.h"
#include "gnss_synchro.h"
#include "pcps_acquisition_fpga.h" #include "pcps_acquisition_fpga.h"
#include <gnuradio/runtime_types.h> // for basic_block_sptr, top_block_sptr #include <gnuradio/runtime_types.h> // for basic_block_sptr, top_block_sptr
#include <volk_gnsssdr/volk_gnsssdr_alloc.h> #include <volk_gnsssdr/volk_gnsssdr_alloc.h>
@ -35,7 +36,6 @@
* \{ */ * \{ */
class Gnss_Synchro;
class ConfigurationInterface; class ConfigurationInterface;
/*! /*!
@ -164,7 +164,6 @@ private:
volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts
std::weak_ptr<ChannelFsm> channel_fsm_; std::weak_ptr<ChannelFsm> channel_fsm_;
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
const ConfigurationInterface* configuration_;
Acq_Conf_Fpga acq_parameters_; Acq_Conf_Fpga acq_parameters_;
std::string role_; std::string role_;
int64_t fs_in_; int64_t fs_in_;

View File

@ -204,7 +204,6 @@ private:
std::weak_ptr<ChannelFsm> channel_fsm_; std::weak_ptr<ChannelFsm> channel_fsm_;
volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts volk_gnsssdr::vector<uint32_t> d_all_fft_codes_; // memory that contains all the code ffts
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
const ConfigurationInterface* configuration_;
Acq_Conf_Fpga acq_parameters_; Acq_Conf_Fpga acq_parameters_;
std::string role_; std::string role_;
int64_t fs_in_; int64_t fs_in_;

View File

@ -34,7 +34,6 @@ void Acq_Conf_Fpga::SetFromConfiguration(const ConfigurationInterface *configura
// downsampling factor // downsampling factor
uint32_t downsampling_factor = configuration->property(role + ".downsampling_factor", downs_factor); uint32_t downsampling_factor = configuration->property(role + ".downsampling_factor", downs_factor);
downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor; fs_in = fs_in / downsampling_factor;
// code length in samples // code length in samples

View File

@ -610,7 +610,7 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
// rx signal vectors // rx signal vectors
std::vector<int8_t> input_samples(sample_block_size * 2); // complex samples std::vector<int8_t> input_samples(sample_block_size * 2); // complex samples
// pointer to DMA buffer // pointer to DMA buffer
std::array<int8_t, BUFFER_SIZE> *dma_buffer; int8_t *dma_buffer;
int nread_elements = 0; // num bytes read from the file corresponding to frequency band 1 int nread_elements = 0; // num bytes read from the file corresponding to frequency band 1
bool run_DMA = true; bool run_DMA = true;
@ -631,8 +631,8 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
// if only one file is enabled then clear the samples corresponding to the frequency band that is not used. // if only one file is enabled then clear the samples corresponding to the frequency band that is not used.
for (int index0 = 0; index0 < (nread_elements); index0 += 2) for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{ {
(*dma_buffer)[dma_index + (2 - dma_buff_offset_pos)] = 0; dma_buffer[dma_index + (2 - dma_buff_offset_pos)] = 0;
(*dma_buffer)[dma_index + 1 + (2 - dma_buff_offset_pos)] = 0; dma_buffer[dma_index + 1 + (2 - dma_buff_offset_pos)] = 0;
dma_index += 4; dma_index += 4;
} }
} }
@ -673,8 +673,8 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
for (int index0 = 0; index0 < (nread_elements); index0 += 2) for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{ {
// dma_buff_offset_pos is 1 for the L1 band and 0 for the other bands // dma_buff_offset_pos is 1 for the L1 band and 0 for the other bands
(*dma_buffer)[dma_index + dma_buff_offset_pos] = input_samples[index0]; dma_buffer[dma_index + dma_buff_offset_pos] = input_samples[index0];
(*dma_buffer)[dma_index + 1 + dma_buff_offset_pos] = input_samples[index0 + 1]; dma_buffer[dma_index + 1 + dma_buff_offset_pos] = input_samples[index0 + 1];
dma_index += 4; dma_index += 4;
} }
@ -704,8 +704,8 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
for (int index0 = 0; index0 < (nread_elements); index0 += 2) for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{ {
// filename2 is never the L1 band // filename2 is never the L1 band
(*dma_buffer)[dma_index] = input_samples[index0]; dma_buffer[dma_index] = input_samples[index0];
(*dma_buffer)[dma_index + 1] = input_samples[index0 + 1]; dma_buffer[dma_index + 1] = input_samples[index0 + 1];
dma_index += 4; dma_index += 4;
} }
} }

View File

@ -23,7 +23,11 @@
#include "concurrent_queue.h" #include "concurrent_queue.h"
#include "fpga_buffer_monitor.h" #include "fpga_buffer_monitor.h"
#include "fpga_dma.h" #if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
#include "fpga_dma-proxy.h"
#else
#include "fpga_ezdma.h"
#endif
#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"

View File

@ -19,8 +19,13 @@ if(ENABLE_FPGA OR ENABLE_AD9361)
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_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) set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_buffer_monitor.h)
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dma.cc) if(ARCH_64BITS)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma.h) set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dma-proxy.cc)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma-proxy.h)
else()
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_ezdma.cc)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_ezdma.h)
endif()
endif() endif()
set(SIGNAL_SOURCE_LIB_SOURCES set(SIGNAL_SOURCE_LIB_SOURCES

View File

@ -1,5 +1,5 @@
/*! /*!
* \file fpga_dma.cc * \file fpga_dma-proxy.cc
* \brief FPGA DMA control. This code is based in the Xilinx DMA proxy test application: * \brief FPGA DMA control. This code is based in the Xilinx DMA proxy test application:
* https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software * https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software
* \author Marc Majoral, mmajoral(at)cttc.es * \author Marc Majoral, mmajoral(at)cttc.es
@ -15,7 +15,7 @@
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/ */
#include "fpga_dma.h" #include "fpga_dma-proxy.h"
#include <fcntl.h> #include <fcntl.h>
#include <iostream> // for std::cerr #include <iostream> // for std::cerr
#include <sys/ioctl.h> // for ioctl() #include <sys/ioctl.h> // for ioctl()
@ -24,7 +24,6 @@
int Fpga_DMA::DMA_open() int Fpga_DMA::DMA_open()
{ {
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
tx_channel.fd = open("/dev/dma_proxy_tx", O_RDWR); tx_channel.fd = open("/dev/dma_proxy_tx", O_RDWR);
if (tx_channel.fd < 1) if (tx_channel.fd < 1)
{ {
@ -40,61 +39,29 @@ int Fpga_DMA::DMA_open()
return -1; return -1;
} }
#else // 32-bit processor architecture
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
return tx_fd;
}
// note: a problem was identified with the DMA: when switching from tx to rx or rx to tx mode
// the DMA transmission may hang. This problem will be fixed soon.
// for the moment this problem can be avoided by closing and opening the DMA a second time
if (close(tx_fd) < 0)
{
std::cerr << "Error closing loop device " << '\n';
return -1;
}
// open the DMA a second time
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
std::cerr << "Cannot open loop device\n";
// stop the receiver
return tx_fd;
}
#endif
return 0; return 0;
} }
int8_t *Fpga_DMA::get_buffer_address() // NOLINT(readability-make-member-function-const)
std::array<int8_t, BUFFER_SIZE> *Fpga_DMA::get_buffer_address() // NOLINT(readability-make-member-function-const)
{ {
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture return tx_channel.buf_ptr[0].buffer;
return &tx_channel.buf_ptr[0].buffer;
#else // 32-bit processor architecture
return &buffer;
#endif
} }
int Fpga_DMA::DMA_write(int nbytes) const int Fpga_DMA::DMA_write(int nbytes) const
{ {
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
int buffer_id = 0; int buffer_id = 0;
tx_channel.buf_ptr[0].length = nbytes; tx_channel.buf_ptr[0].length = nbytes;
// start DMA transfer // start DMA transfer
if (ioctl(tx_channel.fd, START_XFER, &buffer_id)) if (ioctl(tx_channel.fd, _IOW('a', 'b', int32_t *), &buffer_id)) // start transfer
{ {
std::cerr << "Error starting tx DMA transfer " << '\n'; std::cerr << "Error starting tx DMA transfer " << '\n';
return -1; return -1;
} }
// wait for completion of DMA transfer // wait for completion of DMA transfer
if (ioctl(tx_channel.fd, FINISH_XFER, &buffer_id)) if (ioctl(tx_channel.fd, _IOW('a', 'a', int32_t *), &buffer_id)) // finish transfer
{ {
std::cerr << "Error detecting end of DMA transfer " << '\n'; std::cerr << "Error detecting end of DMA transfer " << '\n';
return -1; return -1;
@ -105,27 +72,16 @@ int Fpga_DMA::DMA_write(int nbytes) const
std::cerr << "Proxy DMA Tx transfer error " << '\n'; std::cerr << "Proxy DMA Tx transfer error " << '\n';
return -1; return -1;
} }
#else // 32-bit processor architecture
const int num_bytes_sent = write(tx_fd, buffer.data(), nbytes);
if (num_bytes_sent != nbytes)
{
return -1;
}
#endif
return 0; return 0;
} }
int Fpga_DMA::DMA_close() const int Fpga_DMA::DMA_close() const
{ {
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
if (munmap(tx_channel.buf_ptr, sizeof(struct channel_buffer))) if (munmap(tx_channel.buf_ptr, sizeof(struct channel_buffer)))
{ {
std::cerr << "Failed to unmap DMA tx channel " << '\n'; std::cerr << "Failed to unmap DMA tx channel " << '\n';
return -1; return -1;
} }
return close(tx_channel.fd); return close(tx_channel.fd);
#else // 32-bit processor architecture
return close(tx_fd);
#endif
} }

View File

@ -1,5 +1,5 @@
/*! /*!
* \file fpga_dma.h * \file fpga_dma-proxy.h
* \brief FPGA DMA control. This code is based in the Xilinx DMA proxy test application: * \brief FPGA DMA control. This code is based in the Xilinx DMA proxy test application:
* https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software * https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software
* \author Marc Majoral, mmajoral(at)cttc.es * \author Marc Majoral, mmajoral(at)cttc.es
@ -15,45 +15,11 @@
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/ */
#ifndef GNSS_SDR_FPGA_DMA_PROXY_H
#define GNSS_SDR_FPGA_DMA_PROXY_H
#ifndef GNSS_SDR_FPGA_DMA_H
#define GNSS_SDR_FPGA_DMA_H
#include <array> // for std::array
#include <cstdint> // for std::int8_t #include <cstdint> // for std::int8_t
#define BUFFER_SIZE (128 * 1024) /* must match driver exactly */
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
#define TX_BUFFER_COUNT 1 /* app only, must be <= to the number in the driver */
#define FINISH_XFER _IOW('a', 'a', int32_t *)
#define START_XFER _IOW('a', 'b', int32_t *)
// channel buffer structure
struct channel_buffer
{
std::array<int8_t, BUFFER_SIZE> buffer;
enum proxy_status
{
PROXY_NO_ERROR = 0,
PROXY_BUSY = 1,
PROXY_TIMEOUT = 2,
PROXY_ERROR = 3
} status;
unsigned int length;
} __attribute__((aligned(1024))); /* 64 byte alignment required for DMA, but 1024 handy for viewing memory */
// internal DMA channel data structure
struct channel
{
struct channel_buffer *buf_ptr;
int fd;
};
#endif
/*! /*!
* \brief Class that controls the switch DMA in the FPGA * \brief Class that controls the switch DMA in the FPGA
*/ */
@ -78,7 +44,7 @@ public:
/*! /*!
* \brief Obtain DMA buffer address. * \brief Obtain DMA buffer address.
*/ */
std::array<int8_t, BUFFER_SIZE> *get_buffer_address(void); // NOLINT(readability-make-member-function-const) int8_t *get_buffer_address(void); // NOLINT(readability-make-member-function-const)
/*! /*!
* \brief Transfer DMA data * \brief Transfer DMA data
@ -91,11 +57,30 @@ public:
int DMA_close(void) const; int DMA_close(void) const;
private: private:
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture static const uint32_t DMA_MAX_BUFFER_SIZE = (128 * 1024); /* must match driver exactly */
static const uint32_t TX_BUFFER_COUNT = 1;
// channel buffer structure
struct channel_buffer
{
int8_t buffer[DMA_MAX_BUFFER_SIZE];
enum proxy_status
{
PROXY_NO_ERROR = 0,
PROXY_BUSY = 1,
PROXY_TIMEOUT = 2,
PROXY_ERROR = 3
} status;
unsigned int length;
} __attribute__((aligned(1024))); /* 64 byte alignment required for DMA, but 1024 handy for viewing memory */
// internal DMA channel data structure
struct channel
{
struct channel_buffer *buf_ptr;
int fd;
};
channel tx_channel; channel tx_channel;
#else // 32-bit processor architecture
std::array<int8_t, BUFFER_SIZE> buffer;
int tx_fd;
#endif
}; };
#endif // GNSS_SDR_FPGA_DMA_H #endif // GNSS_SDR_FPGA_DMA_PROXY_H

View File

@ -0,0 +1,68 @@
/*!
* \file fpga_edma.cc
* \brief FPGA DMA control using the ezdma (See https://github.com/jeremytrimble/ezdma).
* \author Marc Majoral, mmajoral(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "fpga_ezdma.h"
#include <fcntl.h>
#include <iostream> // for std::cerr
#include <unistd.h>
int Fpga_DMA::DMA_open()
{
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
return tx_fd;
}
// note: a problem was identified with the DMA: when switching from tx to rx or rx to tx mode
// the DMA transmission may hang. This problem will be fixed soon.
// for the moment this problem can be avoided by closing and opening the DMA a second time
if (close(tx_fd) < 0)
{
std::cerr << "Error closing loop device " << '\n';
return -1;
}
// open the DMA a second time
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
std::cerr << "Cannot open loop device\n";
// stop the receiver
return tx_fd;
}
return 0;
}
int8_t *Fpga_DMA::get_buffer_address()
{
return buffer;
}
int Fpga_DMA::DMA_write(int nbytes) const
{
const int num_bytes_sent = write(tx_fd, buffer, nbytes);
if (num_bytes_sent != nbytes)
{
return -1;
}
return 0;
}
int Fpga_DMA::DMA_close() const
{
return close(tx_fd);
}

View File

@ -0,0 +1,64 @@
/*!
* \file fpga_ezdma.h
* \brief FPGA DMA control using the ezdma (See https://github.com/jeremytrimble/ezdma).
* \author Marc Majoral, mmajoral(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_FPGA_EDMA_H
#define GNSS_SDR_FPGA_EDMA_H
#include <cstdint> // for std::int8_t
/*!
* \brief Class that controls the switch DMA in the FPGA
*/
class Fpga_DMA
{
public:
/*!
* \brief Default constructor.
*/
Fpga_DMA() = default;
/*!
* \brief Default destructor.
*/
~Fpga_DMA() = default;
/*!
* \brief Open the DMA device driver.
*/
int DMA_open(void);
/*!
* \brief Obtain DMA buffer address.
*/
int8_t *get_buffer_address(void); // NOLINT(readability-make-member-function-const)
/*!
* \brief Transfer DMA data
*/
int DMA_write(int nbytes) const;
/*!
* \brief Close the DMA device driver
*/
int DMA_close(void) const;
private:
static const uint32_t DMA_MAX_BUFFER_SIZE = 4 * 16384; // 4-channel 16384-sample buffers
int8_t buffer[DMA_MAX_BUFFER_SIZE];
int tx_fd;
};
#endif // GNSS_SDR_FPGA_EDMA_H