Introduction of EPICS aSub Record

The aSub record is an advanced variant of the 'sub' (subroutine) record with a number of added features:

1) It provides 20 different input and output fields which can hold array or scalar values. The type and array size of these are user configurable, and they all have an associated input or output link.

2) The name of the C or C++ subroutine to be called when the record is running can be dynamically modified when the IOC is running. This name can be retrieved from another record using an input link, or written directly into the SNAM field.

3) The user can choose whether to submit monitor events for this output field.

4) The VAL field is set to the value returned from the user subroutine, which is treated as a status value and controls whether to use this output link. Logging can also generate an alert of the selected severity if the status value is non-zero.

1. Record special menu

1) Menu aSubLFLF

The LFLG menu field controls whether the SUBL link is read to update the name of the subroutine to be called when the record is run.

2) Menu aSubEFLG

The EFLG menu field indicates whether to submit monitor events for the VALA..VALU output value fields. 

2. Parameter field

1) subroutine field

The VAL field is set to the return value of the user subroutine. This value is treated as an error status value (a value of 0 indicates success). Output links OUTA .. OUTU will only be used to forward the associated output value field if this word procedure returns a 0 status. If the returned status is less than 0, the record will enter the SOFT_ALARM state with the severity specified by the BRSV field.

The INAM field can be used to name a subroutine that will be called once when the IOC is initialized.

LFLG tells the record whether this record reads or ignores SUBL links. If the value is READ, the name of the subroutine to be called is read from SUBL at runtime. If this value is IGNORE, the name of the subroutine is currently stored in SNAM.

Reads a string from a SUBL link to get the name of the subroutine to be run when the record is run.

SNAM holds the name of the subroutine to be run when the record is run. If LFLG is set to READ, the value in this field is overwritten by the SUBL link.

The SADR field can only be accessed from C code; it points to the subroutine to be called.

The CADR field is set by the user subroutine to point to another function, which will be called immediately before setting the SARD field to some other routine. This allows only user subroutines to locate resources when they are first called and release them again when they are no longer in use.

2) Operation display parameters

The PREC field specifies the number of decimal places used to display the values ​​of the value fields A...U and VALA...VALU. Except when it doesn't apply.

3) Output Event tag

This field tells this record when to submit change events for the output fields VALA...VALU. If this value is NEVER, no more events are submitted. If this value is ALWAYS, the event is submitted every time the record runs. If this value is ON CHANGE, an event is submitted when any element of an array changes value. This tag controls value, log (archive) and alert change events.

4) Enter the link field

Get the values ​​of A...U from these links when the record runs

 5) Enter the value field

These fields hold scalar or array values ​​taken from input links INPA, ..., INPU.

6) Input value data type

Enter the field type for the value field. These options can be found by linking to the definition of menuFtype.

7) The capacity of the input value array

These fields specify how many array elements this input value field can hold.

 8) Dimensions of the input value array

These fields specify how many array elements the input value field currently contains.

 9) Output link field

At record run time, whenever this procedure returns 0, the VALA, .. VALU field values ​​are sent over these output links.

10) Output value field

These fields hold the scalar or array data generated by this subroutine, which will be sent through the OUTA, ..., OUTU links when the recording is run.

11) Old value field

The previous value of the output field. These fields are used to determine when events are submitted when EFLG is set to ON CHANGE.

12) Output value data type

The field type of the output value field. These options can be found by following the link to the definition of menuFtype.

13) Output value array capacity

These fields specify how many array elements the output value field can hold.

14) Output value array size

These fields specify how many array elements the output value field currently contains.

15) Old value array size

These fields specify how many array elements the old value field currently contains.

2. Record support procedures

1) init_record

  long (*init_record)(struct dbCommon *precord, int pass)

During iocInit, this procedure is called twice. When called for the first time, it does the following:

1) calloc enough space to hold input scalars and/or arrays defined by the settings of the FTA-FTU and NOA-NOU fields. Initializes NE* to the value of the associated NO* field value.
2) calloc enough space to hold the number of output scalars and/or arrays defined by the settings of FTVA-FTVU and NOVA-NOVU. For output fields, calloc space to hold a field's previous value. This is required when deciding whether to submit an event.

In the second call, it does the following:

1) If SUBL is a constant link, initialize SUBL.

2) Initialize each constant input link.

3) If field INAM is set, look up the address of this routine and call it.

4) If the LFLG field is set to IGNORE and SNAM is defined, find the address of the process program.

2) process

long (*process)(struct dbCommon *precord)

This program implements the following algorithm:

1) If PACT is FALSE, perform normal operation.

2) If PACT is TRUE, execution ends the run asynchronously.

normal operation:

  • Set PACT to TRUE.
  • If field LFLG is set to READ, the subroutine name is read from the SUBL link. If this name is not NULL and is different from the previous subroutine name, look up the subroutine address. Set the old subroutine name ONAM to the current name SNAM.
  • Get these values ​​from the input link.
  • Set PACT to FALSE.
  • If all input links are fetched successfully, call the procedure specified by SNAM.
  • Sets VAL to the return value from the program specified by SNAM.
  • Returned if the SNAM program set PACT to TRUE. In this case, we assume that the program has scheduled the process to be called for asynchronous completion at some later time.
  • Set PACT to TRUE.
  • If VAL is 0, use the output link to write the output value.
  • Get the running time and put it into the timestamp field.
  • If VAL changes, submit a value change and log event for this field. If EFLG is set to ALWARYS, submit value changes and log events for each output field. If EFLG is set to ON CHANGE, submit a value change and log event for each output field that changes. In the case of arrays, if any single element in the array changes, an event will be posted. If EFLG is set to NEVER, no value change or log events are submitted for output fields.
  • Run the record at the end of the forward link, if it exists.
  • Set PACT to FALSAE.

A run that ends asynchronously:

  • (again) Call the program specified by SNAM.
  • Sets VAL to the return value from the program specified by SNAM.
  • Set PACT to TRUE.
  • If VAL is 0, use the output link to write the output value.
  • Get the elapsed time and put it into the timestamp field.
  • If VAL changes, submit a value change and log event for this field. If EFLG is set to ALWARYS, submit value changes and log events for each output field. If EFLG is set to ON CHANGE, submit a value change and log event for each output field that changes. In the case of an array, an event will be posted if any single element in the array changes. If EFLG is set to NEVER, no value change or log events are submitted for output fields.
  • Run the record at the end of the forward link if it exists.
  • Set PACT to FALSE.

3. Use of aSub records

An aSub record has an input value field (AU) and an output value field (VALA-VALU), which are completely independent. Input value fields have associated input links (INPA-INPU) and output value fields have associated output links (OUTA-OUTU). Both input and output have type fields (FTA-FTU, FTVA-FTVU, which default to "DOUBLE"), and number of elements fields (NOA-NOU, NOVA-NOVU, which both default to '1'). If this subroutine returns a status value of 0 (OK), the output link OUTA-OUTU is processed.

1) Sample database fragment

To read an array from some other record using the A field, I need a database fragment that looks like this:

 record(aSub,"my_asub_record") {
        field(SNAM,"my_asub_routine")
        ...
        field(FTA, "LONG")
        field(NOA, "100")
        field(INPA, "myWaveform_1 NPP NMS")
        ...
    }

2) Example subroutine fragment

The associated subroutine code using the A field would look like this:

   static long my_asub_routine(aSubRecord *prec) {
        long i, *a;
        double sum=0;
        ...
        a = (long *)prec->a;
        for (i=0; i<prec->noa; i++) {
            sum += a[i];
        }
        ...
        return 0; /* process output links */
    }

NOTE: This subroutine must always handle the value fields (AU, VALA-VALU) as arrays, even if AU, VALA-VALU contains only a single element.

3) need to export the code

In addition to your own code, you must export and register your subroutines so this record can locate them. The easiest way is as follows:

  #include <registryFunction.h>
    #include <epicsExport.h>
    
    static long my_asub_routine(aSubRecord *prec) {
        ...
    }
    epicsRegisterFunction(my_asub_routine);

4) Requires database definition code

The .dbd file loaded by ioc must contain the following line, which tells the linker to include your object file in the IOC program:

 function(my_asub_routine)

5) Device support, write hardware

aSub records do not invoke any supporting routines. If you want to write to hardware, you can use your output field and link to write to some other record that can write to hardware.

6) Dynamically change the called user program during recording operation

The aSub record allows dynamic changes to the called procedure while the record is running. There are two ways of doing this:

1) The LFLG field can be set to READ, thus reading the name of this program from the SUBL link. Thus, anything provided to this link can change the program's name before the aSub record runs. In this case, when the name of the program acquired from the link is changed, the record looks up the symbol name in the symbol table.

2) The LFLG field can be set to IGNORE. In this case, the program called when the record is run is the one specified in the SNAM field. In these cases, the SNAN field can be changed by writing to that field through channel access. In development, it is not necessary to restart the IOC and reload the database when trying several versions of this program. A new program can be loaded with the vxWorkd ld command, and the program name is placed in the SNAM field of the record using the channel access or dbpf command. When the SNAM field is modified, this record will look up the symbol name in the symbol table. It is even possible to use the same program name because the vxWorkd symbol lookup returns the latest version of the code that has been loaded.

Guess you like

Origin blog.csdn.net/yuyuyuliang00/article/details/130307844