mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-01-18 21:23:02 +00:00
use separate files for the Xilinx DMA-proxy and the ezdma drivers
This commit is contained in:
parent
d1c71fbbf7
commit
4ce4682ea8
@ -610,7 +610,7 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
|
||||
// rx signal vectors
|
||||
std::vector<int8_t> input_samples(sample_block_size * 2); // complex samples
|
||||
// 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
|
||||
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.
|
||||
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
|
||||
{
|
||||
(*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 + (2 - dma_buff_offset_pos)] = 0;
|
||||
dma_buffer[dma_index + 1 + (2 - dma_buff_offset_pos)] = 0;
|
||||
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)
|
||||
{
|
||||
// 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 + 1 + dma_buff_offset_pos] = input_samples[index0 + 1];
|
||||
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_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)
|
||||
{
|
||||
// filename2 is never the L1 band
|
||||
(*dma_buffer)[dma_index] = input_samples[index0];
|
||||
(*dma_buffer)[dma_index + 1] = input_samples[index0 + 1];
|
||||
dma_buffer[dma_index] = input_samples[index0];
|
||||
dma_buffer[dma_index + 1] = input_samples[index0 + 1];
|
||||
dma_index += 4;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,11 @@
|
||||
|
||||
#include "concurrent_queue.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_switch.h"
|
||||
#include "gnss_block_interface.h"
|
||||
|
@ -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_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_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dma.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma.h)
|
||||
if(ARCH_64BITS)
|
||||
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()
|
||||
|
||||
set(SIGNAL_SOURCE_LIB_SOURCES
|
||||
|
@ -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:
|
||||
* https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software
|
||||
* \author Marc Majoral, mmajoral(at)cttc.es
|
||||
@ -15,7 +15,7 @@
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "fpga_dma.h"
|
||||
#include "fpga_dma-proxy.h"
|
||||
#include <fcntl.h>
|
||||
#include <iostream> // for std::cerr
|
||||
#include <sys/ioctl.h> // for ioctl()
|
||||
@ -24,7 +24,6 @@
|
||||
|
||||
int Fpga_DMA::DMA_open()
|
||||
{
|
||||
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
|
||||
tx_channel.fd = open("/dev/dma_proxy_tx", O_RDWR);
|
||||
if (tx_channel.fd < 1)
|
||||
{
|
||||
@ -40,61 +39,29 @@ int Fpga_DMA::DMA_open()
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
std::array<int8_t, BUFFER_SIZE> *Fpga_DMA::get_buffer_address() // NOLINT(readability-make-member-function-const)
|
||||
int8_t *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;
|
||||
#else // 32-bit processor architecture
|
||||
return &buffer;
|
||||
#endif
|
||||
return tx_channel.buf_ptr[0].buffer;
|
||||
}
|
||||
|
||||
|
||||
int Fpga_DMA::DMA_write(int nbytes) const
|
||||
{
|
||||
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
|
||||
|
||||
int buffer_id = 0;
|
||||
|
||||
tx_channel.buf_ptr[0].length = nbytes;
|
||||
|
||||
// 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';
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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';
|
||||
return -1;
|
||||
@ -105,27 +72,16 @@ int Fpga_DMA::DMA_write(int nbytes) const
|
||||
std::cerr << "Proxy DMA Tx transfer error " << '\n';
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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)))
|
||||
{
|
||||
std::cerr << "Failed to unmap DMA tx channel " << '\n';
|
||||
return -1;
|
||||
}
|
||||
return close(tx_channel.fd);
|
||||
#else // 32-bit processor architecture
|
||||
return close(tx_fd);
|
||||
#endif
|
||||
}
|
@ -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:
|
||||
* https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software
|
||||
* \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
|
||||
|
||||
#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
|
||||
*/
|
||||
@ -78,7 +44,7 @@ public:
|
||||
/*!
|
||||
* \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
|
||||
@ -91,11 +57,31 @@ public:
|
||||
int DMA_close(void) const;
|
||||
|
||||
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
|
||||
{
|
||||
//std::array<int8_t, BUFFER_SIZE> 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;
|
||||
#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
|
68
src/algorithms/signal_source/libs/fpga_ezdma.cc
Normal file
68
src/algorithms/signal_source/libs/fpga_ezdma.cc
Normal 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);
|
||||
}
|
64
src/algorithms/signal_source/libs/fpga_ezdma.h
Normal file
64
src/algorithms/signal_source/libs/fpga_ezdma.h
Normal 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
|
Loading…
Reference in New Issue
Block a user