The timing/bsa package and the bsaDriver module are in charge of all acquisition services, namely: Beam Line Data (BLD), Beam Synchronous Acquisition (BSA), Beam Synchronous Acquisition Service (BSAS), and Beam Synchronous Scalar Service (BSSS) for the superconducting accelerator. 

timing/bsa package

BsaDefs.hh

BsaDefs.hh

Processor.hh

Processor.hh

Processor.cc

Processor.cc

TBD

Introduction

This contains a list of the capabilities of the module/package i detail. The reader should be able to understand the basic functionalities of this package/module by reading this text.

Package/module file structure

  • AcqServiceYaml.cc/hh : Contains the base class for BSSS and BLD acquisition services. This base class established communication with CPSW, and provides API method to the upper layers to control and acquire data from BLD and BSSS streams.
  • BldYaml.cc/hh : Implements AcqServiceYaml class with 4 Event definitions
  • BsssYaml.cc/hh: Implements AcqServiceYaml class with 9 Event definitions
  • AmcCarrier.cc/hh: 
  • AmcCarrierBase.cc/hh
  • AmcCarrierYaml.cc/hh
  • bld_control.cc
  • bsa_tst.cc
  • bsaapp_tst.cc
  • BsaDefs.ccc/hh
  • BsaField.hh
  • BsasYaml.cc/hh
  • bsayaml_tst.cc
  • cpsw_duo.cc
  • cpsw_tst.cc
  • CpswTemplate.hh
  • cpu_tst.cc
  • Processor.cc/hh
  • ProcessorT.hh
  • RamControl.cc/hh : Defines IRamControl and CRamControlImpl classes. Later on, something called control, waveform1 and waveform2 will be instantiated with IRamControl. Seems like all three have the same memory layout
  • socketAPI.cc/hh : Socket class that opens a socket and sends data over multicast
  • TPG.cc/hh : 
  • TPGMini.cc/hh
  • tpr_stream.cc
  • yaml_tst.cc

YAMLs

The timing/bsa requires paths that will denote the relevant registers/streams/and drams described in the YAML files. The necessary YAML files are as follows

  • BldAxiStream.yaml : used for BLD and BSSS acquisition services


The involved registers are as follows

Register IndexYAML FileStream/Register nameDescription
1

BldAxiStream.yaml







packetSize

Maximum size of packets in 32b words
2

enable

service enable
3

channelMask

Mask of enabled channels
4

currPacketSize

Current size of packet in 32b words
5

currPacketState

Current packet fill state. Relevant to the statemachine filling the packet in the firmware and irrelevant to the software engineer
6

currPulseIdL

Current packet pulseID lower word
7

currTimeStampL

Current packet timestamp lower word
8

currDelta

Current compressed timestamp/pulseID
9

packetCount

Generated packet count
10

paused

Stream paused
11

diagnClockRate

Diagnostic bus clock rate
12

diagnStrobeRate

Diagnostic bus strobe rate
13

eventSel0Rate

Event select0 rate
14

EdefEnable[#EDEFS]

Enable a specific event definition
15

EdefRateLimit[#EDEFS]

Event definition rate limit
16

EdefRateSel[#EDEFS]

Event definition rate select
17

EdefDestSel[#EDEFS]

Event definition destination select












Class(es)/file(es) descriptions

Each file/associated classes will be described here. UML diagrams and text description can be used. A UML cheat sheet can be found here. Instantiation information (if applicable) can be mentioned. Flow diagrams for describing the class operation are also welcome. Everything can be developed in Gliffy. 

Exception handling (if applicable)

Here you can mention if the package/module throws any exceptions, and you can also mention how these exceptions should be handled in upper layers.

Extension (if applicable)

Is the package extendable to add a new function or to modify an existing function? If so, it needs to be mentioned here. 

Exported IOC shell commands, description and parameters (if applicable)

All EPICS shell commands provided should be described here with their input parameters.

PV name list (if applicable)

The PV list goes here. If any other page described some or all PVs, it can be referenced here. The register index can map the PV to the register described in the YAML section above.

bldStream.cpp

Contains functions and structures to read the BLD/BSSS/BSAS stream coming from the firmware and call the registered callback functions with the stream data stored in buffers. It also provides functions to print statistics. This file forms an EPICS driver run at IOC boot automatically without any user setup or configuration. 


bsaDriver class

Detailing of the static functions available in the file

init_drvList find_drvByNamedRoot

get_drvNode

listener

callbacks


Print last buffer

bldStreamDriver


Service Asyn driver (serviceAsynDriver.cpp)

This Asyn driver is used to initialize both BSSS and BLD since they both have identical firmware structures. This file contains some similar structures with bldStream.cpp file. A static pointer is declared globally in the file, and used to store different service drivers in a linked list.

Linked list structure and relevant functions


A simple description of the linked list functions is as follows:

  • init_drvList
    • Returns an allocated global linked list pointer. This does not necessarily mean that the linked l has elements.
    • Flow: If the global pointer is not NULL, a new linked list (type ELLLIST) is allocated, otherwise do nothing. 
  • find_drvLast:
    • Returns the last driver found. If not driver is found in the linked list, NULL is returned
    • Calls init_drvList, then counts the number of elements in the linked list. If they are not 0, it returns the last element, otherwise returns NULL
  • find_drvByPort:
    • Returns a driver that matches the same port name. If not found, returns NULL
    • Calls init_drvList, then iterates on the linked list one element at a time starting from the first element. Once an element with a portName that is not NULL, and a string length of not zero, and a string identical to the argument port_name is found, it is returned, otherwise the next item is examined. If none is found, NULL is returned
  • prep_drvAnonimous:
    • Returns an allocated but empty driver pointer that needs to be initialized
    • Calls init_drvList, then allocates memory for a new item in the linked list, initializes it, then adds it to the end of the linked list and returns linked list count.


Several other independent functions exist in the file. A simple description of these functions is as follows:

  • serviceAdd: (Incorrect naming - Proper naming should be channelAdd). Adds a new channel to the pServiceEllList linked list with the specifications provided
  • associateBsaChannels: Associates all BSA channels to a service; namely : BSSS or BLD. Calls serviceAdd for each of the BSA channels
  • bldChannelName: Associates a channel with an alias (channel name) for printing on the PVXS record describing the BLD packet
  • bsss_callback/bld_callback: Calls the driver callback with the buffer and the size provided 
  • find_pidPv: Returns the structure of a pid (64bit) PV associated with a port, bsakey and and EDEF number
  • find_vPv: Returns the structure of a (double) PV associated with a port, bsakey and and EDEF number
  • serviceMonitorPoll: a thread function that runs infinitely and updates the status parameters (calls method MonitorStatus)


Finally, the serviceAsynDriver class and methods are as follows


serviceAsynDriver class


A description of the class methods is as follows:


  • serviceAsynDriver: Class constructor, Gets root Path from CPSW, creates the <Service>Yaml structure(s) provided by the timing/bsa package, and register callbacks

  • SetupAsynParams: Creates all ASYN parameters the translate to PVs
  • SetRate: set all EDEF rate related configurations (deprecated in BSSS)
  • SetDest: set all EDEF destination related configurations
  • SetChannelSevr: method to set the channel severity private variable
  • GetChannelSevr method to get the channel severity private variable
  • writeInt32: Asyn write 32 bit function used for passing PV values to firmware

  • writeOctet: Asyn write array function used currently only with BLD multicast address

  • updatePVA: Deletes the old PVA and calls initPVA again

  • initPVA: Instantiates the BLD payload PVAccess. IT described the content of the BLD packet

  • addBldChannelName: adds a name to a BLD channel. This replaces the channel key <bsakey> in BLD

  • MonitorStatus: method that reads status variables from the firmware and updates PVs

  • bsssCallback: BSSS built-in callback function

  • bldCallback: BLD built-in callback function

  • getServiceType: Return private variable serviceType

The BLD packet structure coming from the ATCA FPGA and the ones sent out to the BLD clients are described in these slides. The packet structure coming from the firmware contain a packet header, followed by the event's enabled channel data and finally by the severity mask. The firmware may send other event data appended as many times as necessary.

The BSSS firmware packet structure however are not described anywhere.

The packet structure extracted from the bsssCallback seems to be as follows:


BSSS packet structure
struct firmwareBSSSPacket{
	uint64_t sec;
 	uint64_t pid;
	uint32_t channelMask;
	uint32_t serviceMask;
	uint32_t channelData0;
    ...
 	uint32_t channelData30; 
	uint64_t severityMask;
}


The reported number channel data in the packet is variable and not necessarily all of the channels will have data. The BSSS callback source code uses the channelMask to identify if the channel data is available or not.

devBsss.c/devBsss.h (BSSS device support)

This device support for BSSS was developed to override the asyn parameters. Apparently the asyn based PVs increase the CPU load significantly. The header file contains functions that will be accessed by external source to update the relevant records. 2 device support records are created

  • 64-bit integer (devBsssPid)
  • Double (devBsssV)

The device support structures (DSET) are defined as follows

Device support
struct {
        long            number;
        DEVSUPFUN       report;
        DEVSUPFUN       init;
        DEVSUPFUN       init_record;
        DEVSUPFUN       get_ioint_info;
        DEVSUPFUN       read;
}devBsssPid={
        5,
        NULL,
        NULL,
        init_record_pid,
        get_ioint_info,
        read_pid
};

struct {
        long            number;
        DEVSUPFUN       report;
        DEVSUPFUN       init;
        DEVSUPFUN       init_record;
        DEVSUPFUN       get_ioint_info;
        DEVSUPFUN       read;
        DEVSUPFUN       speical_linconv;
}devBsssV={
        6,
        NULL,
        NULL,
        init_record_v,
        get_ioint_info,
        read_v,
        NULL
};

epicsExportAddress(dset, devBsssPid);
epicsExportAddress(dset, devBsssV);

More information about the DSET can be found here. The structure of these structures come from aiRecord.h and int64inRecord.h files. Once the functions are defined and their function addresses are given to the structure, the structures must be exported using the epicsExportAddress command.

The functions are namely as follows:

  • init_record: Runs at each new record initialization. Create a new PV structure - pid_pvt or v_pvt depending on the record type. Checks if record INP is not INST_IO, prints error and exits. otherwise, it looks for the asyn parameters of the associated asyn driver by dissecting the INP field of the instantiated record, and extracting the port, the bsakey and the edef number. Once the reference is found, private pointers are stored.
  • get_ioint_info: This routine is called by the ioEventScan system each time the record is added or deleted from an I/O event scan list. cmd has the value (0,1) if the record is being (added to, deleted from) an I/O event list.
  • read/write; Everytime the record is processed, the new value of the record is determined by this function. If no conversion is done, the new value is written to the val variable and 2 is returned. If conversion is done, the new value is written to rval and 0 is returned.

A graphical structure of t

Pointers between serviceAsynDriver and devBsss

At this point, the device supports exist, but are still not enabled for usage. the new device supports need to be added to the dbd file (bsaAsynDriver.dbd) using the following commands:


Device support DBD commands
device(int64in, INST_IO, devBsssPid, "BSSS")
device(ai,      INST_IO, devBsssV,   "BSSS")

These lines state that the device support devBsssPid overloads the device support of int64in record type, and the devBsssV overloads the device support of ai record type. The last parameter denotes the DTYP field in the db file. The following slides were taken from one of the EPICS trainings may help visualize what is what

                         

BSA asyn driver (bsaAsynDriver.cpp/h)

BSA asyn driver also contains a global static pointer that points to a linkedList of all drivers instantiated, and contains the same set of linkedList functions that were described above. The node structure is as follows

(TODO: convert code into diagram, adding bsaAsynDriver, pBsaEllList, and pBsaBridge)

BSA ELLList node structure
typedef struct {
    ELLNODE       node;
    char          *named_root;
    char          *port;
    bsaAsynDriver *pBsaDrv;
    ELLLIST       *pBsaEllList;
    void          *_pBsaBridge;
} pDrvList_t;

bsaAsynDriver is a class defined in bsaAsynDriver.h: class bsaAsynDriver:asynPortDriver.

The linked list pBsaEllList contains elements of the struct bsaList_t. This struct represents one BSA channel.

bsaList_t
typedef struct {
    ELLNODE  node;
    ELLLIST  *pSlaveEllList;  // slave node
    char     bsa_name[64];    // bsa name
    char     bsa_type[32];    // bsa datatype

    int      firstParam;
    int      p_num[MAX_BSA_ARRAY];           // asyn parameter for number of average, asynFloat64Array, RO
    int      p_mean[MAX_BSA_ARRAY];          // asyn parameter for average value,     asynFloat64Array, RO
    int      p_rms2[MAX_BSA_ARRAY];          // asyn parameter for rms2 value,        asynFloat64Array, RO
    int      p_slope;                        // asyn parameter for linear conversion, asynFloat64, RW
    int      p_offset;                       // asyn parameter for linear conversion, asynFloat64, RW
    int      lastParam;

    double   slope;
    double   offset;

    bsaDataType_t type;

    devBsaPvt_t ppvt_num[MAX_BSA_ARRAY];
    devBsaPvt_t ppvt_mean[MAX_BSA_ARRAY];
    devBsaPvt_t ppvt_rms2[MAX_BSA_ARRAY];

    char     pname_num[MAX_BSA_ARRAY][64];
    char     pname_mean[MAX_BSA_ARRAY][64];
    char     pname_rms2[MAX_BSA_ARRAY][64];

    char     pname_slope[64];
    char     pname_offset[64];
    bool     doNotTouch;

} bsaList_t;

_pBsaBridge receives pProcessor→getHardware(), a class defined in the timing/bsa module.

devBsaPvt_t is defined in the devScBsa.h file:

devBsaPvt_t
typedef struct {
    void *dpvt;
    epicsTimeStamp ts;
    int  nreq;
    int  entry_sz;
    void *bptr;
} devBsaPvt_t;


The functions operating on the linked list are as follows:

  • init_drvList:
  • prep_drvAnonimous:
    • Returns an allocated but empty driver pointer that needs to be initialized
    • Calls init_drvList, then allocates memory for a new item in the linked list, initializes it, then adds it to the end of the linked list and returns linked list count.
  • prep_drvByPort
    • Same as prep_drvAnonimous; create new driver item of linked list but with a specific port name string
  • prep_drvByNamedRoot: 
    • Same as prep_drvAnonimous; create new driver item of linked list but with a specific named root string
  • find_drvLast. Returns the last driver found. If no driver is found in the linked list, NULL is returned.
    • Starting by calling init_drvList to make sure a linked list is initialized
    • Counts the number of elements in the linked list.
    • If they are not 0, returns the last element, otherwise returns the pointer to the empty list.
  • find_drvByPort:
    • Returns a driver that matches the same port name. If not found, returns NULL
    • Calls init_drvList, then iterates on the linked list one element at a time starting from the first element. Once an element with a portName that is not NULL, and a string length of not zero, and a string identical to the argument port_name is found, it is returned, otherwise the next item is examined. If none is found, NULL is returned
  • find_drvyNamedRoot:
    • Returns a driver that matches the same named root. If not found, returns NULL
    • Calls init_drvList, then iterates on the linked list one element at a time starting from the first element. Once an element with a named_root that is not NULL, and a string length of not zero, and a string identical to the argument name_root is found, it is returned, otherwise the next item is examined. If none is found, NULL is returned

bsaAdd() function

bsaAdd() initializes a bsaList_t structure and stores it in the pBsaEllList ELL linked list. pBsaEllList is stored in the structure pDrvList_t of the bsaAsynDriver.cpp file. There are different structures named as pDrvList_t in other files of the bsaDriver EPICS module, so care must be taken to not get confused. This is a visual pointer structure operated by bsaAdd():

bsaAdd pointer structure

The software assumes that the sequence of commands called in the IOC's st.cmd file is the following:

  1. cpswLoadYamlFile(), from the yamlLoader EPICS module.
  2. One or more bsaAdd().
  3. Zero or more bsaAddSecondary().
  4. bsaAsynDriverConfigure().

If the IOC controls more than one ATCA carrier board, then steps 1 to 4 above are repeated in the same order. If, for example, you called all 4 commands above for board 1, it is not possible to call bsaAdd() expecting it will be applied to board 1 again. After bsaAsynDriverConfigure() the door is closed to add additional BSA channels.

bsaAdd() starts by searching for getting the last element of the pDrvEllList linked list. This is the list that contains the configuration for each ATCA carrier board. One element of this list corresponds to one carrier board. The software assumes that the last element of the list is the one that is still open to receive BSA channels with bsaAdd(). It obtains the last element and check if the pointer to a pBsaDrv is null or if the port is still not defined. These two configurations only happen when bsaAsynDriverConfigure() is called. If the driver was not configured yet, then we are adding BSA channels to the right pDrvList_t. In case the driver is configured, this means that addBsa was called for the first time after cpswLoadYamlFile(). This way, a new pDrvList_t element must be created and appended to the end of the pDrvEllList linked list.





  • No labels