EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message
From: Abdalla Ahmad via Tech-talk <tech-talk at aps.anl.gov>
To: Mark Rivers <rivers at cars.uchicago.edu>, Michael Davidsaver <mdavidsaver at gmail.com>, "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Wed, 18 Nov 2020 09:08:12 +0000
Hello Mark

Sorry for the late response. Attached is the backtrace and the database. The crash happens if I use any record other than the waveform record. Also attached the driver source code.

Thank you very much.
Abdalla.

From: Mark Rivers <rivers at cars.uchicago.edu>
Sent: Thursday, November 5, 2020 6:55 PM
To: Abdalla Ahmad <Abdalla.Ahmad at sesame.org.jo>; Michael Davidsaver <mdavidsaver at gmail.com>; tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>
Subject: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message
 
> Right now I can't get my machine to enable core dumps in order to view the gdb backtrace,


You don't need to enable core dumps.  You can run the IOC within gdb to start with, and then you just issue the backtrace command at the gdb prompt

gdb [path_to_IOC]
gdb> run st.cmd
[crash]
gdb> backtrace

Mark


________________________________
From: Abdalla Ahmad <Abdalla.Ahmad at sesame.org.jo>
Sent: Thursday, November 5, 2020 10:23 AM
To: Mark Rivers; Michael Davidsaver; tech-talk at aps.anl.gov
Subject: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message

Hi Mark

I meant is it possible to set the NORD field in asyn port driver? Right now I can't get my machine to enable core dumps in order to view the gdb backtrace, but I just found out that every time I request a large buffer, I get a received byte count of 1448 which is the maximum data size in a TCP packet. I'll try to handle such case and see what happens.

Best Regards,
Abdalla.
________________________________
From: Mark Rivers <rivers at cars.uchicago.edu>
Sent: Thursday, November 5, 2020 6:15 PM
To: Abdalla Ahmad <Abdalla.Ahmad at sesame.org.jo>; Michael Davidsaver <mdavidsaver at gmail.com>; tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>
Subject: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message

> Regarding EPICS waveforms, what I meant is variable length from the client side;

> For example I set a buffer size in a PV and based on that PV value I read a specific length so that a plotter for example reads data with that specific length only.
> Does NORD achieve this?


NORD controls the maximum number of elements that can be read from the record.  It is the number of "available" elements.  You can request fewer elements in a read requests as well.


> If yes, how does asyn access individual record's fields?.

I am not sure what you mean by that question.

Have you been able to get a gdb traceback of your access violation problem?

Mark


________________________________
From: Abdalla Ahmad <Abdalla.Ahmad at sesame.org.jo>
Sent: Thursday, November 5, 2020 9:46 AM
To: Michael Davidsaver; Mark Rivers; tech-talk at aps.anl.gov
Subject: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message

Hi all.

Buffer size is 48 because the device sends waveform data in lines so I read each line separately by reading 48 bytes, If I request ADC 200 for example I receive 200 lines where each line is 48 bytes. I even did a test where I used a buffer size of 1M to receive the full 20000 lines and still got the same error.

Regarding EPICS waveforms, what I meant is variable length from the client side; For example I set a buffer size in a PV and based on that PV value I read a specific length so that a plotter for example reads data with that specific length only. Does NORD achieve this? If yes, how does asyn access individual record's fields?.

Best Regards,
Abdalla.
________________________________
From: Michael Davidsaver <mdavidsaver at gmail.com>
Sent: Tuesday, November 3, 2020 7:18 PM
To: Mark Rivers <rivers at cars.uchicago.edu>; Abdalla Ahmad <Abdalla.Ahmad at sesame.org.jo>; tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>
Subject: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message

On 11/3/20 8:49 AM, Mark Rivers via Tech-talk wrote:
> -          I don’t think EPICS supports variable length waveform records.  You need to create the waveform record in dbLoadRecords with a size that is the largest you plan to use.  That is what areaDetector does with NDPluginStdArrays.

To clarify, waveform records have a _maximum_ size which is fixed
on initialization (eg. NELM).  Actually size (NORD) has long been
changeable at runtime in the range [0, NELM].

Some caveats about NORD==0 apply wrt. CA specifically (works fine with PVA).
dbGetLinkValue: Illegal link type -12704

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffee1a8700 (LWP 26466)]
recGblSetSevr (precord=precord@entry=0x3737382d20202020, new_stat=new_stat@entry=14, new_sevr=new_sevr@entry=3) at ../../../src/ioc/db/recGbl.c:219
219	../../../src/ioc/db/recGbl.c: No such file or directory.
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-28.el7_5.1.x86_64 libstdc++-4.8.5-28.el7_5.1.x86_64 ncurses-libs-5.9-14.20130511.el7_4.x86_64 readline-6.2-10.el7.x86_64
(gdb) backtrace
#0  recGblSetSevr (precord=precord@entry=0x3737382d20202020, new_stat=new_stat@entry=14, new_sevr=new_sevr@entry=3) at ../../../src/ioc/db/recGbl.c:219
#1  0x00007ffff74995af in dbGetLink (plink=0x6d0d28, dbrType=dbrType@entry=3, pbuffer=pbuffer@entry=0x6d0d22, poptions=poptions@entry=0x0, pnRequest=pnRequest@entry=0x0) at ../../../src/ioc/db/dbLink.c:658
#2  0x00007ffff74a546e in recGblGetTimeStamp (pvoid=pvoid@entry=0x6d0c70) at ../../../src/ioc/db/recGbl.c:257
#3  0x00007ffff770d3a7 in process (prec=0x6d0c70) at ../../../src/std/rec/longinRecord.c:152
#4  0x00007ffff74a5721 in ProcessCallback (pcallback=<optimized out>) at ../../../src/ioc/db/callback.c:307
#5  0x00007ffff74a569c in callbackTask (arg=<optimized out>) at ../../../src/ioc/db/callback.c:175
#6  0x00007ffff6fd18ec in start_routine (arg=0x6e2480) at ../../../src/libCom/osi/os/posix/osdThread.c:403
#7  0x00007ffff618ee25 in start_thread () from /lib64/libpthread.so.0
#8  0x00007ffff64a1bad in clone () from /lib64/libc.so.6
(gdb)

Attachment: libera-spark.db
Description: libera-spark.db

#include "drvLiberaSpark.h"

static void* start_daq_thread(void* pvt)
{
	((LiberaSpark*) pvt)->performDAQ();
	return NULL;
}

LiberaSpark::LiberaSpark(const char* port_name, const char* hostname)
	    : asynPortDriver(port_name,
                     1,
                     asynInt32Mask | asynOctetMask | asynInt64Mask | asynInt32ArrayMask | asynDrvUserMask,
                     0,
                     ASYN_MULTIDEVICE | ASYN_CANBLOCK,
                     1,
                     0, 0),
		adc_a{0}
{
    createParam(P_VERSION,  asynParamOctet, &index_version);
    createParam(P_KX,       asynParamInt32, &index_kx);
    createParam(P_KY,       asynParamInt32, &index_ky);
    createParam(P_KQ,       asynParamInt32, &index_kq);
    createParam(P_XOFF,     asynParamInt32, &index_xoff);
    createParam(P_YOFF,     asynParamInt32, &index_yoff);
    createParam(P_QOFF,     asynParamInt32, &index_qoff);
    createParam(P_ADC_SIZE, asynParamInt64, &index_adc_size);
    createParam(P_TRIG_DELAY, asynParamInt32, &index_trig_delay);
    createParam(P_MAF_LENGTH, asynParamInt32, &index_maf_length);
    createParam(P_TRIGGER_TIME, asynParamOctet, &index_trigger_time);
    createParam(P_FILL_COUNT, asynParamInt32, &index_fill_count);
    createParam(P_RESET_COUNT, asynParamInt32, &index_reset_count);
    createParam(P_TRIGGER,     asynParamInt32, &index_trigger);
    createParam(P_START, asynParamInt32, &index_start);
    createParam(P_STATUS, asynParamOctet, &index_status);
	createParam(P_ADC_A, asynParamInt32Array, &index_adc_a);

    struct hostent* hosts = gethostbyname(hostname);
    if(hosts == NULL)
    {
        printf("Could not resolve hostname %s\n", hostname);
        this->device_socket = -1;
    }
    else
    {
        char* ip = inet_ntoa( *(struct in_addr*) hosts->h_addr);
        this->device_socket = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in address;
        address.sin_family = AF_INET;
        address.sin_port = htons(23);
        address.sin_addr.s_addr = inet_addr(ip);
        if(::connect(this->device_socket, (sockaddr*) &address, sizeof(address)) == -1)
        {
            perror("connect");
            this->device_socket = -1;
        }
		else
		{
			size_t length = strlen(COMMAND_START);
			size_t bytes = write(device_socket, COMMAND_START, length);
			if(bytes != length)
			{
				fprintf(stderr, "Could not initialize device %s\n", hostname);
				this->device_socket = -1;
			}
			else
			{
				char buffer[50];
				read(this->device_socket, buffer, sizeof(buffer));
				printf("Device %s initialized successfully\n", hostname);
			}
		}
    }

	if(pthread_create(&daq_thread, 0, start_daq_thread, this) != 0)
	{
		fprintf(stderr, "Could not start data acquistion thread!\n");
		perror("pthread_create");
	}
	else
	{
		pthread_mutex_init(&device_mutex, NULL);
		perror("pthread_mutex_init");
	}
}

asynStatus LiberaSpark::readInt32(asynUser *pasynUser, epicsInt32 *value)
{
	int function = pasynUser->reason;
	char* command;

	if(function == index_kx)
		command = strdup(COMMAND_READ_KX);
	else if(function == index_ky)
		command = strdup(COMMAND_READ_KY);
	else if(function == index_kq)
		command = strdup(COMMAND_READ_KQ);
	else if(function == index_xoff)
		command = strdup(COMMAND_READ_XOFF);
	else if(function == index_yoff)
		command = strdup(COMMAND_READ_YOFF);
	else if(function == index_qoff)
		command = strdup(COMMAND_READ_QOFF);
    else if(function == index_trig_delay)
        command = strdup(COMMAND_READ_TRIG_DELAY);
    else if(function == index_maf_length)
        command = strdup(COMMAND_READ_MAF_LENGTH);
    else if(function == index_fill_count)
        command = strdup(COMMAND_READ_FILL_COUNT);
    else if(function == index_reset_count || 
			function == index_trigger || 
			function == index_start)
        return asynSuccess;
	else
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Unknown readInt32 function\n");
		return asynError;
	}

	ssize_t length = strlen(command);
	pthread_mutex_lock(&device_mutex);
	ssize_t bytes = write(device_socket, command, length);
	if(bytes != length)
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Could not send command KX to device\n");
		return asynError;
	}

	char buffer[20];
	bytes = read(this->device_socket, buffer, sizeof(buffer));
	if(bytes == -1)
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Error reading KX from device\n");
		return asynError;
	}
	pthread_mutex_unlock(&device_mutex);

	int v = 0;
	if(sscanf(buffer, "%d", &v) == -1)
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Could not parse KX value\n");
		return asynError;
	}
	
	*value = strtol(buffer, NULL, 10);
	return asynSuccess;
}

asynStatus LiberaSpark::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
    int function = pasynUser->reason;
	char* command;
    char buffer[100];
    ssize_t bytes;
    ssize_t length;

	if(function == index_kx)
		command = strdup(COMMAND_WRITE_KX);
    else if(function == index_ky)
		command = strdup(COMMAND_WRITE_KY);
	else if(function == index_kq)
		command = strdup(COMMAND_WRITE_KQ);
	else if(function == index_xoff)
		command = strdup(COMMAND_WRITE_XOFF);
	else if(function == index_yoff)
		command = strdup(COMMAND_WRITE_YOFF);
	else if(function == index_qoff)
		command = strdup(COMMAND_WRITE_QOFF);
    else if(function == index_trig_delay)
        command = strdup(COMMAND_WRITE_TRIG_DELAY);
    else if(function == index_maf_length)
        command = strdup(COMMAND_WRITE_MAF_LENGTH);
    else if(function == index_reset_count)
        command = strdup(COMMAND_RESET_FILL_COUNT);
    else if(function == index_trigger)
        command = strdup(COMMAND_TRIGGER);
    else if(function == index_start)
        command = strdup(COMMAND_START);
	else
	{
        asynPrint(pasynUser, ASYN_TRACE_ERROR, "Unknown writeInt32 function\n");
        return asynError;
	}

    snprintf(buffer, sizeof(buffer), command, value);
    length = strlen(buffer);
	pthread_mutex_lock(&device_mutex);
    bytes = write(this->device_socket, buffer, strlen(buffer));
    if(bytes != length)
    {
        fprintf(stderr, "Could not send %s", buffer);
        return asynError;
    }

    memset(buffer, 0, sizeof(buffer));
    bytes = read(this->device_socket, buffer, sizeof(buffer));
	pthread_mutex_unlock(&device_mutex);

    if(function == index_start && bytes == -1)
    {
        fprintf(stderr, "Could not set START command");
        return asynError;
    }
    else if(function != index_start && (bytes == -1 || strncmp(buffer, "OK", 2) != 0))
    {
        fprintf(stderr, "Could not set %s", command);
        return asynError;
    }

    callParamCallbacks(0);
    return asynSuccess;
}

asynStatus LiberaSpark::readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason)
{
	int function = pasynUser->reason;
	char* command;

	if(function == index_version)
        command = strdup(COMMAND_READ_VER);
    else if(function == index_trigger_time)
        command = strdup(COMMAND_READ_TRIGGER_TIME);
    else if(function == index_status)
        command = strdup(COMMAND_READ_STATUS);
    else
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Unknown readOctet function\n");
		return asynError;
	}

    *nActual = 0;
	ssize_t length = strlen(command);
	pthread_mutex_lock(&device_mutex);
	ssize_t bytes  = write(this->device_socket, command, length);
	if(bytes != length)
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Could not read version\n");
		return asynError;
	}

	char buffer[1000];
    memset(buffer, 0, sizeof(buffer));
	bytes = read(this->device_socket, buffer, sizeof(buffer));
	pthread_mutex_unlock(&device_mutex);
	if(bytes == -1)
	{
		perror("read");
		return asynError;
	}

    length = strlen(buffer);
    buffer[length - 1] = '\0';
	strncpy(value, buffer, length);
	*nActual = length;
	*eomReason = ASYN_EOM_EOS;
	return asynSuccess;
}

asynStatus LiberaSpark::readInt64(asynUser* pasynUser, epicsInt64* value)
{
    int function = pasynUser->reason;
    char* command;
    ssize_t length;
    ssize_t bytes;
    char buffer[50];

    if(function == index_adc_size)
        command = strdup(COMMAND_READ_ADC_SIZE);
    else
    {
        fprintf(stderr, "Unknown readInt64 function\n");
        return asynError;
    }

    length = strlen(command);
	pthread_mutex_lock(&device_mutex);
    bytes = write(this->device_socket, command, length);
    if(bytes != length)
    {
        fprintf(stderr, "Could not send %s", command);
        return asynError;
    }

    memset(buffer, 0, sizeof(buffer));
    bytes = read(this->device_socket, buffer, sizeof(buffer));
	pthread_mutex_unlock(&device_mutex);
    if(bytes == -1)
    {
        fprintf(stderr, "Could not read ADC_SIZE\n");
        return asynError;
    }

    uint64_t v = 0;
	if(sscanf(buffer, "%lu", &v) == -1)
	{
		asynPrint(pasynUser, ASYN_TRACE_ERROR, "Could not parse KX value\n");
		return asynError;
	}
	
    *value = v;
	// *value = strtoll(buffer, NULL, 10);
    return asynSuccess;
}

asynStatus LiberaSpark::writeInt64(asynUser* pasynUser, epicsInt64 value)
{
    int function = pasynUser->reason;
    char* command;
    char buffer [100];
    ssize_t length, bytes;
    
    if(function == index_adc_size)
        command = strdup(COMMAND_WRITE_ADC_SIZE);
    else
    {
        fprintf(stderr, "Unkown writeInt64 function\n");
        return asynError;
    }

    snprintf(buffer, sizeof(buffer), command, value);
    length = strlen(buffer);
	pthread_mutex_lock(&device_mutex);
    bytes = write(this->device_socket, buffer, length);
    if(bytes != length)
    {
        fprintf(stderr, "Could not send %s", buffer);
        return asynError;
    }

    memset(buffer, 0, sizeof(buffer));
    bytes = read(this->device_socket, buffer, sizeof(buffer));
	pthread_mutex_unlock(&device_mutex);
    if(bytes == -1 || strncmp(buffer, "OK", 2) != 0)
    {
        fprintf(stderr, "Could not set %s", command);
        return asynError;
    }
    return asynSuccess;
}

asynStatus LiberaSpark::readInt32Array(asynUser *pasynUser, epicsInt32 *value, size_t nElements, size_t *nIn)
{
	int count = 0;
	for(size_t i = 0; i < nElements; i++)
	{
		if(adc_a[i] != 0)
			count++;
		*(value + i) = adc_a[i];
	}
	*nIn = count;
	cout << *nIn << endl;
	return asynSuccess;
}

void LiberaSpark::performDAQ()
{
	printf("DAQ Thread initialized!\n");

	string line = "";
	char command[20] = "ADC 200\n";
	int status;
	ssize_t bytes;
	char buffer[1000000];
	struct pollfd polling_fds[1];

	polling_fds[0].fd = this->device_socket;
	polling_fds[0].events = POLLIN;
	polling_fds[0].revents = 0;
	while(true)
	{
		lock();
		pthread_mutex_lock(&device_mutex);

		bytes = write(device_socket, command, strlen(command));

		status = poll(polling_fds, 1, 1);
		int i = 0;
		while(status > 0)
		{
			memset(buffer, 0, sizeof(buffer));
			// bytes = read(device_socket, buffer, 48);
			bytes = recv(this->device_socket, buffer, 200*48, MSG_WAITALL);
			buffer[bytes - 1] = '\0';
			stringstream ss(buffer);
			cout << "Size: " << ss.str() << endl;
			while(ss >> line)
			{
				if(i % 4 == 0)
					adc_a[i / 4] = atoi(line.c_str());
				i++;
				line.clear();
			}
			status = poll(polling_fds, 1, 1);
		}
	
		pthread_mutex_unlock(&device_mutex);
		unlock();
		sleep(1);
	}
}

extern "C" int LiberaSparkConfigure(const char *portName, const char* hostname)
{
    new LiberaSpark(portName, hostname);
    return asynSuccess;
}

static const iocshArg configArg0 = { "Host name", iocshArgString };
static const iocshArg configArg1 = { "Port name", iocshArgString };
static const iocshArg * const configArgs[] = {&configArg0, &configArg1};
static const iocshFuncDef configFuncDef = {"LiberaSparkConfigure",2,configArgs};
static void configCallFunc(const iocshArgBuf *args)
{
    LiberaSparkConfigure(args[0].sval, args[1].sval);
}

void drvLiberaSparkRegister(void)
{
    iocshRegister(&configFuncDef,configCallFunc);
}

extern "C" {
epicsExportRegistrar(drvLiberaSparkRegister);
}
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright (C) Abdalla Al-Dalleh <abdallah.ahmad at sesame.org.jo>, 2020
 *
 *
 * @file    drvMUX.h
 * @author  Abdalla Al-Dalleh (abdallah.ahmad at sesame.org.jo)
 * @date    2020-10-21
 * @brief   Header file for driver support implementation for Libera Spark
 *          beam position monitor using asynPortDriver.
 */

#include <epicsExport.h>
#include <asynPortDriver.h>
#include <iocsh.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>
#include <poll.h>
#include <sys/select.h>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <sstream>

using std::string;
using std::stoi;
using std::stringstream;
using std::cout;
using std::endl;

#define P_VERSION	"version"
#define P_KX		"kx"
#define P_KY		"ky"
#define P_KQ		"kq"
#define P_XOFF		"xoff"
#define P_YOFF		"yoff"
#define P_QOFF		"qoff"
#define P_ADC_SIZE	"adc_size"
#define P_TRIG_DELAY	"trigger_delay"
#define P_MAF_LENGTH	"maf_length"
#define P_TRIGGER_TIME	"trigger_time"
#define P_FILL_COUNT	"fill_count"
#define P_RESET_COUNT	"reset_fill_count"
#define P_TRIGGER		"trigger"
#define P_START			"start"
#define P_STATUS		"status"
#define P_ADC_A			"adc_a"

#define DELIM		"\n"
#define COMMAND_START     "START" DELIM
#define COMMAND_READ_KX   "KX?"   DELIM
#define COMMAND_READ_KY   "KY?"   DELIM
#define COMMAND_READ_KQ   "KQ?"   DELIM
#define COMMAND_READ_XOFF "XOFF?"   DELIM
#define COMMAND_READ_YOFF "YOFF?"   DELIM
#define COMMAND_READ_QOFF "QOFF?"   DELIM
#define COMMAND_READ_VER  "VER?"    DELIM
#define COMMAND_READ_ADC_SIZE	"ADC_SIZE?" DELIM
#define COMMAND_READ_TRIG_DELAY	"TRIG_DELAY?" DELIM
#define COMMAND_READ_MAF_LENGTH	"MAF_LENGTH?" DELIM
#define COMMAND_READ_TRIGGER_TIME	"TRIG_TM?"	DELIM
#define COMMAND_READ_FILL_COUNT		"FILL_CNT?" DELIM
#define COMMAND_READ_STATUS			"STT?" DELIM

#define COMMAND_WRITE_KX	"KX %d" DELIM
#define COMMAND_WRITE_KY	"KY %d" DELIM
#define COMMAND_WRITE_KQ	"KQ %d" DELIM
#define COMMAND_WRITE_XOFF	"XOFF %d" DELIM
#define COMMAND_WRITE_YOFF	"YOFF %d" DELIM
#define COMMAND_WRITE_QOFF	"QOFF %d" DELIM
#define COMMAND_WRITE_ADC_SIZE	"ADC_SIZE %lld" DELIM
#define COMMAND_WRITE_TRIG_DELAY	"TRIG_DELAY %d" DELIM
#define COMMAND_WRITE_MAF_LENGTH	"MAF_LENGTH %d" DELIM
#define COMMAND_RESET_FILL_COUNT	"FILL_CNT:RST" DELIM
#define COMMAND_TRIGGER				"TRIG" DELIM
#define COMMAND_START				"START" DELIM

#define BUFFER_SIZE		20000

class LiberaSpark : public asynPortDriver
{
public:
	LiberaSpark(const char* port_name, const char* name);
	virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
	virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
	virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason);
	virtual asynStatus readInt64(asynUser *pasynUser, epicsInt64 *value);
	virtual asynStatus writeInt64(asynUser *pasynUser, epicsInt64 value);
	virtual asynStatus readInt32Array(asynUser *pasynUser, epicsInt32 *value, size_t nElements, size_t *nIn);
	void performDAQ();

	int device_socket;
	pthread_t daq_thread;
	pthread_mutex_t device_mutex;

	int adc_a[BUFFER_SIZE];
	int adc_b[BUFFER_SIZE];
	int adc_c[BUFFER_SIZE];
	int adc_d[BUFFER_SIZE];

protected:
	int index_kx;
	int index_ky;
	int index_kq;
	int index_xoff;
	int index_yoff;
	int index_qoff;
	int index_version;
	int index_adc_size;
	int index_trig_delay;
	int index_maf_length;
	int index_trigger_time;
	int index_fill_count;
	int index_reset_count;
	int index_status;
	int index_start;
	int index_trigger;
	int index_adc_a;
};

Replies:
Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Mark Rivers via Tech-talk
References:
AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Abdalla Ahmad via Tech-talk
RE: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Mark Rivers via Tech-talk
Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Michael Davidsaver via Tech-talk
Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Abdalla Ahmad via Tech-talk
Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Mark Rivers via Tech-talk
Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Abdalla Ahmad via Tech-talk
Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Mark Rivers via Tech-talk

Navigate by Date:
Prev: Re: Building StreamDevice with PCRE failing Johnson, Andrew N. via Tech-talk
Next: Re: Building StreamDevice with PCRE failing Christoph Schroeder via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
Navigate by Thread:
Prev: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Mark Rivers via Tech-talk
Next: Re: AsynPortDriver separate thread causes Segmentation fault with "dbGetLinkValue" error message Mark Rivers via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
ANJ, 18 Nov 2020 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·