1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-15 20:50:33 +00:00

Merge branch 'fpga' of https://github.com/mmajoral/gnss-sdr into next

This commit is contained in:
Carles Fernandez 2018-08-14 14:09:10 +02:00
commit edf82644f2
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
2 changed files with 147 additions and 5 deletions

View File

@ -35,6 +35,14 @@
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <glog/logging.h>
#include <fcntl.h> // libraries used by the GIPO
#include <sys/mman.h> // libraries used by the GIPO
#include <inttypes.h>
#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map
#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw)
gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(double _fs, int32_t _interval_ms) : gr::block("fpga_fpga_sample_counter", gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(double _fs, int32_t _interval_ms) : gr::block("fpga_fpga_sample_counter",
gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0),
@ -44,11 +52,15 @@ gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(double _fs, int32_t _
set_max_noutput_items(1); set_max_noutput_items(1);
interval_ms = _interval_ms; interval_ms = _interval_ms;
fs = _fs; fs = _fs;
//printf("CREATOR fs = %f\n", fs);
//printf("CREATOR interval_ms = %" PRIu32 "\n", interval_ms);
samples_per_output = std::round(fs * static_cast<double>(interval_ms) / 1e3); samples_per_output = std::round(fs * static_cast<double>(interval_ms) / 1e3);
//printf("CREATOR samples_per_output = %" PRIu32 "\n", samples_per_output);
//todo: Load here the hardware counter register with this amount of samples. It should produce an //todo: Load here the hardware counter register with this amount of samples. It should produce an
//interrupt every samples_per_output count. //interrupt every samples_per_output count.
//The hardware timer must keep always interrupting the PS. It must not wait for the interrupt to //The hardware timer must keep always interrupting the PS. It must not wait for the interrupt to
//be served. //be served.
open_device();
sample_counter = 0ULL; sample_counter = 0ULL;
current_T_rx_ms = 0; current_T_rx_ms = 0;
@ -75,6 +87,10 @@ gnss_sdr_fpga_sample_counter_sptr gnss_sdr_make_fpga_sample_counter(double _fs,
bool gnss_sdr_fpga_sample_counter::start() bool gnss_sdr_fpga_sample_counter::start()
{ {
//todo: place here the RE-INITIALIZATION routines. This function will be called by GNURadio at every start of the flowgraph. //todo: place here the RE-INITIALIZATION routines. This function will be called by GNURadio at every start of the flowgraph.
// configure the number of samples per output in the FPGA and enable the interrupts
configure_samples_per_output(samples_per_output);
// return true if everything is ok. // return true if everything is ok.
return true; return true;
} }
@ -85,6 +101,8 @@ bool gnss_sdr_fpga_sample_counter::stop()
{ {
//todo: place here the routines to stop the associated hardware (if needed).This function will be called by GNURadio at every stop of the flowgraph. //todo: place here the routines to stop the associated hardware (if needed).This function will be called by GNURadio at every stop of the flowgraph.
// return true if everything is ok. // return true if everything is ok.
close_device();
return true; return true;
} }
@ -101,6 +119,15 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
// Possible problem: what happen if the PS is overloaded and gnuradio does not call this function // Possible problem: what happen if the PS is overloaded and gnuradio does not call this function
// with the sufficient rate to catch all the interrupts in the counter. To be evaluated later. // with the sufficient rate to catch all the interrupts in the counter. To be evaluated later.
uint32_t counter = wait_for_interrupt_and_read_counter();
uint64_t samples_passed = 2*static_cast<uint64_t>(samples_per_output) - static_cast<uint64_t>(counter); // ellapsed samples
//printf("============================================ interrupter : samples_passed = %" PRIu64 "\n", samples_passed);
// Note: at this moment the sample counter is implemented as a sample counter that decreases to zero and then it is automatically
// reloaded again and keeps counter. It is done in this way to minimize the logic in the FPGA and maximize the FPGA clock performance
// (it takes less resources and latency in the FPGA to compare a number against a fixed value like zero than to compare it to a programmable
// variable number).
sample_counter = sample_counter + samples_passed; //samples_per_output;
Gnss_Synchro *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]); Gnss_Synchro *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]);
out[0] = Gnss_Synchro(); out[0] = Gnss_Synchro();
out[0].Flag_valid_symbol_output = false; out[0].Flag_valid_symbol_output = false;
@ -109,6 +136,10 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
out[0].fs = fs; out[0].fs = fs;
if ((current_T_rx_ms % report_interval_ms) == 0) if ((current_T_rx_ms % report_interval_ms) == 0)
{ {
//printf("time to print sample_counter = %" PRIu64 "\n", sample_counter);
//printf("time to print current Tx ms : %" PRIu64 "\n", current_T_rx_ms);
//printf("time to print report_interval_ms : %" PRIu32 "\n", report_interval_ms);
//printf("time to print %f\n", (current_T_rx_ms % report_interval_ms));
current_s++; current_s++;
if ((current_s % 60) == 0) if ((current_s % 60) == 0)
{ {
@ -166,6 +197,109 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
} }
} }
out[0].Tracking_sample_counter = sample_counter; out[0].Tracking_sample_counter = sample_counter;
current_T_rx_ms = (sample_counter * 1000) / samples_per_output; //current_T_rx_ms = (sample_counter * 1000) / samples_per_output;
current_T_rx_ms = interval_ms*(sample_counter) / samples_per_output;
return 1; return 1;
} }
uint32_t gnss_sdr_fpga_sample_counter::test_register(uint32_t writeval)
{
uint32_t readval;
// write value to test register
map_base[3] = writeval;
// read value from test register
readval = map_base[3];
// return read value
return readval;
}
void gnss_sdr_fpga_sample_counter::configure_samples_per_output(uint32_t interval)
{
// note : the counter is a 48-bit value in the HW.
//printf("============================================ total counter - interrupted interval : %" PRIu32 "\n", interval);
//uint64_t temp_interval;
//temp_interval = (interval & static_cast<uint32_t>(0xFFFFFFFF));
//printf("LSW counter - interrupted interval : %" PRIu32 "\n", static_cast<uint32_t>(temp_interval));
//map_base[0] = static_cast<uint32_t>(temp_interval);
map_base[0] = interval - 1;
//temp_interval = (interval >> 32) & static_cast<uint32_t>(0xFFFFFFFF);
//printf("MSbits counter - interrupted interval : %" PRIu32 "\n", static_cast<uint32_t>(temp_interval));
//map_base[1] = static_cast<uint32_t>(temp_interval); // writing the most significant bits also enables the interrupts
}
void gnss_sdr_fpga_sample_counter::open_device()
{
// open communication with HW accelerator
if ((fd = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_name << std::endl;
}
map_base = reinterpret_cast<volatile uint32_t *>(mmap(NULL, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (map_base == reinterpret_cast<void *>(-1))
{
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
std::cout << "Counter-Intr: cannot map deviceio" << device_name << std::endl;
}
// sanity check : check test register
uint32_t writeval = TEST_REG_SANITY_CHECK;
uint32_t readval;
readval = gnss_sdr_fpga_sample_counter::test_register(writeval);
if (writeval != readval)
{
LOG(WARNING) << "Acquisition test register sanity check failed";
}
else
{
LOG(INFO) << "Acquisition test register sanity check success!";
//std::cout << "Acquisition test register sanity check success!" << std::endl;
}
}
void gnss_sdr_fpga_sample_counter::close_device()
{
//printf("=========================================== NOW closing device ...\n");
map_base[2] = 0; // disable the generation of the interrupt in the device
uint32_t *aux = const_cast<uint32_t *>(map_base);
if (munmap(static_cast<void *>(aux), PAGE_SIZE) == -1)
{
printf("Failed to unmap memory uio\n");
}
close(fd);
}
uint32_t gnss_sdr_fpga_sample_counter::wait_for_interrupt_and_read_counter()
{
int32_t irq_count;
ssize_t nb;
int32_t counter;
// enable interrupts
int32_t reenable = 1;
write(fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t));
// wait for interrupt
//printf("============================================ interrupter : going to wait for interupt\n");
nb = read(fd, &irq_count, sizeof(irq_count));
//printf("============================================ interrupter : interrupt received\n");
//printf("interrupt received\n");
if (nb != sizeof(irq_count))
{
printf("acquisition module Read failed to retrieve 4 bytes!\n");
printf("acquisition module Interrupt number %d\n", irq_count);
}
// acknowledge the interrupt
map_base[1] = 0; // writing anything to reg 1 acknowledges the interrupt
// add number of passed samples or read the current counter value for more accuracy
counter = samples_per_output; //map_base[0];
return counter;
}

View File

@ -45,13 +45,18 @@ class gnss_sdr_fpga_sample_counter : public gr::block
{ {
private: private:
gnss_sdr_fpga_sample_counter(double _fs, int32_t _interval_ms); gnss_sdr_fpga_sample_counter(double _fs, int32_t _interval_ms);
uint32_t test_register(uint32_t writeval);
void configure_samples_per_output(uint32_t interval);
void close_device(void);
void open_device(void);
bool start(); bool start();
bool stop(); bool stop();
uint32_t wait_for_interrupt_and_read_counter(void);
uint32_t samples_per_output; uint32_t samples_per_output;
double fs; double fs;
uint64_t sample_counter; uint64_t sample_counter;
int32_t interval_ms; uint32_t interval_ms;
int64_t current_T_rx_ms; // Receiver time in ms since the beginning of the run uint64_t current_T_rx_ms; // Receiver time in ms since the beginning of the run
uint32_t current_s; // Receiver time in seconds, modulo 60 uint32_t current_s; // Receiver time in seconds, modulo 60
bool flag_m; // True if the receiver has been running for at least 1 minute bool flag_m; // True if the receiver has been running for at least 1 minute
uint32_t current_m; // Receiver time in minutes, modulo 60 uint32_t current_m; // Receiver time in minutes, modulo 60
@ -61,6 +66,9 @@ private:
uint32_t current_days; // Receiver time in days since the beginning of the run uint32_t current_days; // Receiver time in days since the beginning of the run
int32_t report_interval_ms; int32_t report_interval_ms;
bool flag_enable_send_msg; bool flag_enable_send_msg;
int32_t fd; // driver descriptor
volatile uint32_t *map_base; // driver memory map
std::string device_name = "/dev/uio26"; // HW device name
public: public:
friend gnss_sdr_fpga_sample_counter_sptr gnss_sdr_make_fpga_sample_counter(double _fs, int32_t _interval_ms); friend gnss_sdr_fpga_sample_counter_sptr gnss_sdr_make_fpga_sample_counter(double _fs, int32_t _interval_ms);