mirror of
https://github.com/EEVengers/ThunderScope.git
synced 2025-04-22 17:43:44 +00:00
Merge pull request #221 from profezzorn/scope_link_linux_support
initial linux support
This commit is contained in:
commit
4e96caf224
@ -13,7 +13,7 @@ CPPOPT := -fopt-info-loop-optimized
|
||||
CPPMISS := -fopt-info-vec-missed
|
||||
CFLAGS := -Wall
|
||||
LDFLAGS := -Llib
|
||||
LDLIBS := -lm -lftd3xx -lstdc++ -pthread -lboost_system -lboost_thread
|
||||
LDLIBS := -lm -lstdc++ -pthread -lboost_system -lboost_thread
|
||||
LDLIBS += -lpthread -lboost_log_setup -lboost_log
|
||||
|
||||
.PHONY: all clean
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
#ifndef PCIe_HPP
|
||||
#define PCIe_HPP
|
||||
|
||||
@ -7,17 +5,29 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <strsafe.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <strsafe.h>
|
||||
#include <Windows.h>
|
||||
#include <SetupAPI.h>
|
||||
#include <INITGUID.H>
|
||||
#include <WinIoCtl.h>
|
||||
|
||||
#include "xdma_public.h"
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define HANDLE int
|
||||
#define INVALID_HANDLE_VALUE -1
|
||||
#endif
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma comment(lib, "setupapi.lib")
|
||||
#endif
|
||||
|
||||
#define USER_DEVICE_PATH "user"
|
||||
#define C2H_0_DEVICE_PATH "c2h_0"
|
||||
@ -121,11 +131,10 @@ private:
|
||||
|
||||
char user_device[20] = USER_DEVICE_PATH; //write/read registers
|
||||
char c2h_0_device[20] = C2H_0_DEVICE_PATH; //read memory
|
||||
HANDLE user_handle;
|
||||
HANDLE user_handle = INVALID_HANDLE_VALUE;
|
||||
char user_connection_string[261] = "";
|
||||
HANDLE c2h_0_handle;
|
||||
HANDLE c2h_0_handle = INVALID_HANDLE_VALUE;
|
||||
char c2h_0_connection_string[261] = "";
|
||||
LARGE_INTEGER freq; //used for perforamnce testing
|
||||
int64_t last_chunk_read;
|
||||
|
||||
//current state
|
||||
@ -139,8 +148,8 @@ private:
|
||||
boost::lockfree::queue<buffer*, boost::lockfree::fixed_sized<false>> *outputQueue;
|
||||
|
||||
//used for speed testing
|
||||
LARGE_INTEGER tick1;
|
||||
LARGE_INTEGER tick2;
|
||||
std::chrono::high_resolution_clock::time_point tick1;
|
||||
std::chrono::high_resolution_clock::time_point tick2;
|
||||
|
||||
void _Read(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToRead);
|
||||
void _Write(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToWrite);
|
||||
@ -165,4 +174,4 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,15 +1,23 @@
|
||||
|
||||
|
||||
#include "PCIe.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/*
|
||||
* get_devices -- Ripped from Xilinx examples
|
||||
* returns the number of XDMA devices
|
||||
*/
|
||||
static int get_devices(GUID guid, char* devpath, size_t len_devpath) {
|
||||
|
||||
HDEVINFO device_info = SetupDiGetClassDevs((LPGUID)&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (device_info == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "GetDevices INVALID_HANDLE_VALUE\n");
|
||||
@ -22,7 +30,6 @@ static int get_devices(GUID guid, char* devpath, size_t len_devpath) {
|
||||
// enumerate through devices
|
||||
DWORD index;
|
||||
for (index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &guid, index, &device_interface); ++index) {
|
||||
#ifdef WIN32 //So i dont know how to change this is work on unix, since HeapAlloc is windows specific, so since Unix does not work with PCIe yet, just ingore this code
|
||||
// get required buffer size
|
||||
ULONG detailLength = 0;
|
||||
if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, NULL, 0, &detailLength, NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
@ -45,7 +52,6 @@ static int get_devices(GUID guid, char* devpath, size_t len_devpath) {
|
||||
}
|
||||
StringCchCopy(devpath, len_devpath, dev_detail->DevicePath);
|
||||
HeapFree(GetProcessHeap(), 0, dev_detail);
|
||||
#endif
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(device_info);
|
||||
@ -111,9 +117,38 @@ int PCIeLink::Connect() {
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#define CloseHandle(X) close(X)
|
||||
|
||||
static int OpenHelper(int n, const char* postfix) {
|
||||
char device_path[128];
|
||||
snprintf(device_path, sizeof(device_path), "/dev/xdma%d_%s", n, postfix);
|
||||
int fd = open(device_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
fprintf(stderr, "failed to open: %s, errno=%d\n", device_path, errno);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
int PCIeLink::Connect() {
|
||||
int device_num = 0;
|
||||
connected = false;
|
||||
user_handle = OpenHelper(device_num, USER_DEVICE_PATH);
|
||||
if (user_handle <= 0) return -1;
|
||||
c2h_0_handle = OpenHelper(device_num, C2H_0_DEVICE_PATH);
|
||||
if (c2h_0_handle <= 0) return -1;
|
||||
connected = true;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************
|
||||
* Read()
|
||||
* Takes in an 8MegaByte buffer (2^23 bytes) and fills it with adc data read from the board
|
||||
@ -480,7 +515,9 @@ void PCIeLink::_FIFO_WRITE(HANDLE hPCIE, uint8_t* data, uint8_t bytesToWrite) {
|
||||
_Read(user_handle,SERIAL_FIFO_TDFV_ADDRESS,tdfvBuff,4);
|
||||
}
|
||||
|
||||
void PCIeLink::_Read(HANDLE hPCIE, int64_t address, uint8_t* buff, int bytesToRead) {
|
||||
|
||||
#ifdef WIN32
|
||||
void PCIeLink::_Read(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToRead) {
|
||||
if(hPCIE == INVALID_HANDLE_VALUE) {
|
||||
ERROR << "INVALID HANDLE PASSED INTO PCIeLink::_Read(): " << hPCIE;
|
||||
return;
|
||||
@ -500,7 +537,7 @@ void PCIeLink::_Read(HANDLE hPCIE, int64_t address, uint8_t* buff, int bytesToRe
|
||||
}
|
||||
}
|
||||
|
||||
void PCIeLink::_Write(HANDLE hPCIE, int64_t address, uint8_t* buff, int bytesToWrite) {
|
||||
void PCIeLink::_Write(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToWrite) {
|
||||
if(hPCIE == INVALID_HANDLE_VALUE) {
|
||||
ERROR << "INVALID HANDLE PASSED INTO PCIeLink::_Write(): " << hPCIE;
|
||||
return;
|
||||
@ -519,35 +556,43 @@ void PCIeLink::_Write(HANDLE hPCIE, int64_t address, uint8_t* buff, int bytesToW
|
||||
ERROR << "_Write() failed with Win32 error code: " << GetLastError();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
void PCIeLink::_Read(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToRead) {
|
||||
// TODO: EINTR handling if needed.
|
||||
ssize_t ret = pread(hPCIE, buff, bytesToRead, address);
|
||||
if (ret != bytesToRead) {
|
||||
perror("pread");
|
||||
}
|
||||
}
|
||||
|
||||
void PCIeLink::_Write(HANDLE hPCIE, long long address, uint8_t* buff, int bytesToWrite) {
|
||||
// TODO: EINTR handling if needed.
|
||||
ssize_t ret = pwrite(hPCIE, buff, bytesToWrite, address);
|
||||
if (ret != bytesToWrite) {
|
||||
perror("pwrite");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void PCIeLink::_Write32(HANDLE hPCIE, long long address, uint32_t val) {
|
||||
if(hPCIE == INVALID_HANDLE_VALUE) {
|
||||
ERROR << "INVALID HANDLE PASSED INTO PCIeLink::_Write(): " << hPCIE;
|
||||
return;
|
||||
}
|
||||
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = address;
|
||||
// set file pointer to offset of target address within PCIe BAR
|
||||
if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hPCIE, offset, NULL, FILE_BEGIN)) {
|
||||
ERROR << "Error setting file pointer for PCIeLink::_Write(), win32 error code: " << GetLastError();
|
||||
}
|
||||
|
||||
// write from buffer to device
|
||||
DWORD bytesWritten;
|
||||
uint8_t bytes[4];
|
||||
bytes[3] = (uint8_t)( (val & 0xFF000000) >> 24);
|
||||
bytes[2] = (uint8_t)( (val & 0x00FF0000) >> 16);
|
||||
bytes[1] = (uint8_t)( (val & 0x0000FF00) >> 8);
|
||||
bytes[0] = (uint8_t)( (val & 0x000000FF));
|
||||
if (!WriteFile(hPCIE, bytes, 4, &bytesWritten, NULL)) {
|
||||
ERROR << "_Write() failed with Win32 error code: " << GetLastError();
|
||||
}
|
||||
_Write(hPCIE, address, bytes, 4);
|
||||
}
|
||||
|
||||
void PCIeLink::_Job() {
|
||||
bool priority = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
#ifdef WIN32
|
||||
bool priority = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
INFO << "THREAD_PRIORITY_TIME_CRITICAL: " << priority;
|
||||
#endif
|
||||
while(_run.load()) {
|
||||
while(_pause.load()) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(100));
|
||||
@ -573,7 +618,6 @@ PCIeLink::PCIeLink(boost::lockfree::queue<buffer*, boost::lockfree::fixed_sized<
|
||||
user_handle = INVALID_HANDLE_VALUE;
|
||||
c2h_0_handle = INVALID_HANDLE_VALUE;
|
||||
last_chunk_read = -1;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
this->outputQueue = outputQueue;
|
||||
//keep the read thread alive but paused
|
||||
_run = true;
|
||||
@ -660,11 +704,11 @@ PCIeLink::~PCIeLink() {
|
||||
}
|
||||
|
||||
void PCIeLink::ClockTick1() {
|
||||
QueryPerformanceCounter(&tick1);
|
||||
tick1 = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void PCIeLink::ClockTick2() {
|
||||
QueryPerformanceCounter(&tick2);
|
||||
tick2 = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
@ -675,15 +719,13 @@ void PCIeLink::ClockTick2() {
|
||||
*
|
||||
*************************************************************/
|
||||
void PCIeLink::PrintTimeDelta() {
|
||||
double time_sec = (unsigned long long)(tick2.QuadPart - tick1.QuadPart) / (double)freq.QuadPart;
|
||||
INFO << "Time Delta is: " << time_sec;
|
||||
INFO << "Time Delta is: " << GetTimeDelta();
|
||||
}
|
||||
|
||||
double PCIeLink::GetTimeDelta() {
|
||||
return (unsigned long long)(tick2.QuadPart - tick1.QuadPart) / (double)freq.QuadPart;
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(tick2 - tick1).count() / 1000000000.0;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************ SCOPE CONTROL STUFF ***********************************************/
|
||||
|
||||
int PCIeLink::_ch_on(int ch_num){
|
||||
|
Loading…
Reference in New Issue
Block a user