Epics async port driver




















The actual code is more complicated because it unlocks before it calls code outside asynManager. This means that the queues can be modified and exceptions may occur. A special record type asynRecord is provided. Details are described in asynRecord. This section provides a brief description of how to use it.

The example creates a record with name "asynTest" formed from the concatenation of the P and R macros that will connect to port "L0" and addr Thus a single record can be used to access all asyn devices connected to the IOC. Multiple records are only needed if one or more devices need a dedicated record. The asynDriver distribution includes code to test asynDriver.

It is also an example of how to interface to asynManager. It implements asynCommon and asynOctet. When asynOctet:write is called it saves the message.

When asynOctet:read is called the saved message is returned and the message is flushed. The string records attach to the device support supplied by devAsynTest. The stringout and stringin records share the same asynUser. When the stringout record processes it:. This starts two versions of echoDriver as port "A" and "B".

For each of the three possible devices, the st. It also loads a set of records from asynGeneric. It provides gpib specific functions like SRQ handling. It makes calls to asynGpibPort.

Note that asynGpib. Default values are enclosed in square brackets. It just issues read requests until no bytes are read. The timeout is used for the read requests. Examples are:. Since asynDriver does NOT provide support for specific devices an application must obtain device specific support elsewhere. This section only explains how to include asynDriver components. In the st. Once asynRecord is started it can be connected to different devices.

The caller did not supply a buffer large enough to hold all input. What happens to the remaining bytes depends on the low level driver. Queue a connect or disconnect request. This is set by the user and can be changed between calls to drivers. The user must provide a non zero value or many low level drivers will timeout.

For use by the user. If this is changed while asynUser is queued, the results are undefined, e. Any method can provide additional return information in auxStatus. The meaning is determined by the method. Reports status about the asynPortManager. It also calls asynCommon:report for each registered port driver. Creates an asynUser. The caller specifies two callbacks, one for successful queueRequests and one if a queueRequest has a timeout. The timeout callback is optional. If it is not provided and a queueRequest with a non-zero timeout is requested, an error message is issued and no timeout will occur.

The amount of storage can not be changed. This method doesn't return if it is unable to allocate the storage. Free an asynUser. The user must free an asynUser only via this call. The call will fail if the asynUser is connected to a device. Does the port support multiple devices? This method can be called before calling connectDevice. Device code calls this to connect to a device. Typically the record type will be longin or mbbiDirect. If attempts to communicate with a device result in error messages of the form "Access denied insufficient permissions " you must add udev entries to allow access.

To allow everyone in the "usbtmc" group access to a device with vendor code 1BFA hexadecimal and product code hexadecimal the line would look like:.

The USBTMC driver attempts to take correct action when it detects that the device has been unplugged or become unresponsive. The effectiveness of this depends somewhat on the level of support provided by the underlying operating system so it is good practice to also specify the following StreamDevice global exception handlers:. The drivers noted above are included as part of the ASYN distribution. Additional drivers are available, including:. This is a base class from which real asyn port drivers can be derived.

It greatly simplifies the job of writing an asyn port driver, because it takes care of all of the tasks like registering the port, registering the interfaces, and calling interrupt clients. It is documented separately in asynPortDriver. They handle the details of connecting to the driver, finding the required interfaces, etc.

They only uses the synchronous interfaces, so all calls are blocking. It is documented separately in asynPortClient. It just issues read requests until no bytes are left to read. The timeout is used for the read requests. If portName is zero length then the global trace mask is set. If portName is zero length then the global traceIO mask is set.

If portName is zero length then the global traceInfo mask is set. The filename is handled as follows:. The entry is a character string constant that identifys the port,addr. Examples are:. The time stamp source function must be defined as a "function" in the application dbd file. This reverts to the default timestamp source function in asynManager. After obtaining a copy of the distribution, it must be installed and built for use at your site.

Since asynDriver does NOT provide support for specific devices an application must obtain device specific support elsewhere. This section only explains how to include asynDriver components. Once asynRecord is started, it can be connected to different devices.

Figure 1: Asynchronous Control Flow. Figure 2: Synchronous Control Flow. Standard Message Based Interfaces. Standard Register Based Interfaces. Standard Interpose Interfaces.

The driver has lost input data. This can happen if an internal buffer or the user supplied buffer is too small. Whenever possible, low level drivers should be written so that the user can read input in small pieces. Queue a connect or disconnect request. The error message should not end with nor contain a newline character sequence e.

It is up to user code to decide whether and how to display the error message. Keeping newlines out of the error message make it easy for user code to embed the error message in another message or output format. This is set by the user and can be changed between calls to a driver.

For use by the user. A driver can use this to hold asynUser specific data. The asynDrvUser interface is used for communication between asynUser and the driver. Drivers and asynUsers can use this as a general purpose field. By convention it is used to determine what "command" is being sent over a particular interface.

Typically drivers implement the asynDrvUser interface, and use this to convert from descriptive strings for commands e. A driver that is calling an interrupt users often uses reason to decide if the users callback should be called. Values of reason less than 0 are reserved for standard meanings. The devGpib support uses this to report SRQs. Devices which provide their own time stamps use this field to provide the time value for records whose TSE field is set to "-2".

Any method can provide additional return information in auxStatus. The meaning is determined by the method. Callbacks use auxStatus to set record alarm status in device support callback functions. Reports status about the asynPortManager.

It also calls asynCommon:report for each port being reported. Creates an asynUser. The caller specifies two callbacks, process and timeout. These callback are only called as a result of a queueRequest. The timeout callback is optional. The amount of storage can not be changed. This method doesn't return if it is unable to allocate the storage.

Creates an asynUser by calling createAsynUser. It then initializes the new asynUser as follows: The fields timeout, userPvt, userData, and drvUser are initialized with values taken from pasynUser. Its connectDevice state is the same as that for pasynUser. Free an asynUser. The user must free an asynUser only via this call.

If the asynUser is connected to a port, asynManager:disconnect is called. If the disconnect fails, this call will also fail. The storage for the asynUser is saved on a free list and will be reused in later calls to createAsynUser or duplicateAsynUser. Answers the question "Does the port support multiple devices?

Connect the asynUser structure to a device specified by portName, addr. The port Name is the same as that specified in a call to registerPort. The call will fail if the asynUser is already connected to a device. If the port does not support multiple devices, than addr is ignored.

The port driver may or may not be connected to the actual device. Thus, connectDevice and asynCommon:connect are completely different. Disconnect the asynUser from the port,addr to which it is connected via a previous call to connectDevice. The call will fail if the asynUser is queued or locked, or has a callback registered via exceptionCallbackAdd.

Note that asynManager:disconnect and asynCommon:disconnect are completely different. Callback will be called whenever one of the exceptions defined by asynException occurs. The callback can call isConnected, isEnabled, or isAutoConnect to find the connection state. Find a driver interface. If interposeInterfaceOK is true, then findInterface returns the last interface registered or interposed. Otherwise, the interface registered by registerPort is returned. It returns 0 if the interfaceType is not supported.

If a asynUser is queued, remove it from the queue. If either the process or timeout callback is active when cancelRequest is called than cancelRequest will not return until the callback completes. Note the following restrictions for blockProcessCallback: blockProcessCallback only works with drivers that can block and an error is returned if it is called for non-blocking drivers. It is permissible to simultaneously block allDevices and also the device to which the asynUser is connected.

Lock access to a port driver. This is used by code that is willing to block while making calls to a port driver. The code can call lockPort, make an arbitrary number of calls to the port driver, and than call unlockPort. The difference between lockPort and queueLockPort is that queueLockPort queues a request to lock the port, using the same queues as queueRequest.

This means that a thread that repeatedly calls queueLockPort without sleeping between calls will still allow other threads to access the port. This is not true with lockPort, which will take a mutex as soon as the port is free, and can prevent other threads from accessing the port at all. The value is determined by the attributes passed to registerPort. This method is called by drivers. A call is made for each port instance.

Attributes is a set of bits. The driver must specify these properly. If priority is 0, then the default value epicsThreadPriorityMedium will be assigned.

The portName argument specifies the name by which the upper levels of the asyn code will refer to this communication interface instance. The registerPort method makes an internal copy of the string to which the name argument points. This is called by port drivers for each supported interface. This method does not make a copy of the asynInterface to which the pasynInterface argument points. Callers must store the asynInteface in a location which is retained for the lifetime of the port. This is commonly done by placing the asynInterface structure in the 'driver private' structure.

This method must be called by the driver when and only when it connects to a port or device. This method must be called by the driver when and only when it disconnects from a port or device. This is called by a software layer between client code and the port driver.

For example, if a device echos writes then a software module that issues a read after each write could be created and call interposeInterface for interface asynOctet. If enable is set yes, then queueRequests are not dequeued unless their queue timeout occurs.

See the discussion of Flow of Control below for details. Changes the timeout when waiting for the initial connection callback from port drivers. This callback occurs in response to asynManager queueing a connection request, which happens when the port driver registers its asynCommon interface. The default timeout is 0. If a low level driver supports interrupts it must call this for each interface that supports interrupts.

This argument is passed interruptStart and interruptEnd. Any code that wants to call createInterruptNode but does not know the adresss of pasynPvt can find it via this method. The caller must be connected to a device, i. If the caller is not connected, getInterruptPvt returns asynError.

These methods are the only way a user can allocate and free an interruptNode. If either of these is called while a interrupt is being processed, i. The process callback for the asynUser specified in the call to addInterruptUser must not call removeInterruptUser or it will block forever. The code that implements interrupts is interface dependent. The only service asynManager provides is a thread-safe implemention of the user list. When the code wants to call the callback specified in the calls to registerInterruptUser, it calls interruptStart to obtain the list of callbacks.

When it is done it calls interruptEnd. Unregisters any user-defined timestamp callback function and reverts to the default timestamp source function in asynManager, which simply calls epicsTimeGetCurrent.

Set the current time stamp for this port by calling either the default timestamp source, or a user-defined timestamp source that was registered with registerTimeStampSource. Get the current time stamp for this port that was returned by the most recent call to updateTimeStamp. Set the current time stamp for this port directly from the timestamp value passed to this function. Generates a report about the hardware device.

Connect to the hardware device or communication path. The queueRequest must specify priority asynQueuePriorityConnect. Disconnect from the hardware device or communication path. The user, i. The driver can create any resources it needs. If the asynUser and the driver both know how to access the resources they must agree about the name for the resource and a size.

Unless asynUser receives a typeName and size that it recognizes it must not access asynUser. If other code, e. In the iocsh and vxWorks shells this is done by using a leading 0 on the number, i. There is no special device support provided as part of modbus. It is necessary to use asyn R or later, because some minor enhancements were made to asyn to support the features required by modbus.

The drvUser parameter is used by the driver to determine what command is being sent from device support. Records can override the default Modbus data type by specifying datatype-specific drvUser field, e.

The offset parameter is used to specify the location of the data for a record relative to the starting Modbus address for that driver.

This offset is specified in bits for drivers using Modbus functions 1, 2, 5, and 15 that control discrete inputs or coils. If absolute addressing is being used then the offset parameter is an absolute bit Modbus address, and is not relative to the starting Modbus address, which is The offset is specified in words for drivers using Modbus functions 3, 4, 6 and 16 that address input registers or holding registers. Note: when writing bit or bit values function code 16 should be used if the device supports it.

The write will then be "atomic". If function code 6 is used then the data will be written in multiple messages, and there will be an short time period in which the device has incorrect data.

Note: The 0 terminating byte at the end of the string in a waveform record or stringout record is not written to the Modbus device. The string will be truncated if any of the characters read from Modbus is a 0 byte, but there is no guarantee that the last character in the string is followed by a 0 byte in the Modbus registers.

Generally either modbusLength or NELM in the waveform record should be used to define the correct length for the string. These include:. This application can be run to control any number of Modbus PLCs. The following is the beginning of Koyo1. Note that this example is designed for testing and demonstration purposes, not as a realistic example of how modbus would normally be used. For example, it loads 6 drivers to access the C control relays using function codes 1 read coils , 3 read holding registers , 5 write single coil , 6 write single holding register , 15 write multiple coils , and 16 write multiple holding registers.

This allows for testing of all function codes and record types, including waveforms. In practice one would normally only load at most 2 drivers for the C control relays, for example function code 1 read coils , and function code 5 write single coil. These examples are used for testing the different Modbus data types and other features. I have used them with the Modbus Slave program, which is an inexpensive Modbus slave emulator.

There is another test application called testClient. The same code could be used in a driver in an IOC. One can obtain diagnostic output for a modbus port driver using the "dbior" or "asynPrint" commands at the iocsh or vxWorks shell.

For example, a partial output for the Koyo1 application when it is connected via TCP is:. For example the following screen shots shows the asyn record being used to control output Y1 on a PLC. Each time the asyn record is processed the value will be sent to the PLC. The following are the main enhancements of modbus compared to the modtcp and plctcp packages from Triumf:. The following are some drawbacks of modbus compared to the modtcp and plctcp packages from Triumf:.

This value will be written to the Y1 output when the record is processed. RTU is normally run over serial communication links, i. The protocol directly transmits each byte as 8 data bits, so uses "binary" rather than ASCII encoding. When using serial links start and end of message frames is detected by timing rather than by specific characters.

Serial protocol, which is normally run over serial communication links, i. This protocol is less efficient than RTU, but may be more reliable in some environments. The timeout in milliseconds for write and read operations to the underlying asynOctet driver. If zero is specified then a default timeout of milliseconds is used. This is typically only needed for Serial RTU devices. When registerPort is called, the caller must specify if it can block, i.

In either case the process callback specified in the call to createAsynUser is called. If the asynUser is already on a queue, asynError is returned. The timeout starts when the request is queued.

A value less than or equal to 0. The request is removed from the queue before the callback is called. Callbacks are allowed to make requests to asynManager such as queueRequest, blockProcessCallback, etc.

It is even permissible to call freeAsynUser from a callback but the request will be delayed until after the callback completes. If a timeout callback was not passed to createAsynUser and a queueRequest with a non-zero timeout is requested, the request fails.

Thus the software module that last called interposeInterface is called by user code. It in turn can call the software module that was the second to last to call interposeInterface. This continues until the actual port driver is called. Thus, new interfaces that are unknown to the low level driver can be implemented. The code does not need to handle callbacks or understand the details of the asynManager and asynCommon interfaces.

This is provided for port drivers that are an asynUser of another port driver. When the serial bus port is locked, either by the requester calling lockPort or because a queueRequest was dequeued, then the serial bus driver needs to lock the associated serial port.

The serial bus driver registers interface asynLockPortNotify. Whenever the serial bus port is locked, asynManager calls pasynLockPortNotify. The serial bus driver calls asynManager. Similarly for unlockPort. Thus while the serial bus port is locked, the serial bus is also locked. It is not put in the list of interfaces for the port. For example the serial port driver uses this to specify baud rate, stop bits, etc.

In order for the trace facility to perform properly; device support and all drivers must use the trace facility. Device and driver support can directly call the asynTrace methods.

Support can have calls like:. The asynPrintIO call is designed for device support or drivers that issue read or write requests. They make calls like:. The asynTrace methods are implemented by asynManager. These methods can be used by any code that has created an asynUser and is connected to a device. All methods can be called by any thread.

If the asynUser is not connected to a port, i. This is useful when asynPrint is called before connectDevice. Except for setTraceFile the set methods do not block, since worst that can happen is that the user gets a little more or a little less output. These are interfaces for communicating with message based devices, where message based means that the device communicates via octet strings, i. It's primary putpose is to help with interrupt support.

For single device support, it can optionally implement interrupt support. A driver that implements interrupts must call registerInterruptSource. Any null method in the interface passed to initialize are replaced by a method supplied by asynOctetBase. The code does not need to handle callbacks or understand the details of the asynManager and asynOctet interfaces.

Examples include motor drivers running in their own threads, SNL programs, and the shell commands described later in this document. It does not specify policy. Device support code, interpose layers, or low level drivers can all handle EOS processing.

An application developer must decide what policy will be followed for individual devices. The policy will be determined by the device, the device support, and the driver.

Note that hardware may have registers with smaller sizes, e. The standard interfaces can still be used by setting the unused bits to 0.

In addition a default implementation and a synchronous inplementation are provided. Lets use Int32 as an example. An example is a 16 channel ADC. The driver implements interfaces asynCommon and asynInt It uses interface asynInt32Base. It can call asynManager:interruptStart and asynManager:interruptEnd to support interrupts. An example is a 64 bit combination digital input and digital output module. The driver implements interfaces asynCommon and asynUInt32Digital.

It uses interface asynUInt32DigitalBase. It can use reason, mask, and addr to decide which callbacks to call. The driver must itself call the callbacks via calls to asynManager:interruptStart and asynManager:interruptEnd.

The code that calls it must be willing to block. This means that pFloat64ArrayInterface should NOT be that address of static storage because initialize replaces the null methods with an override method. A new asynInterface must be allocated for each port instance.

An easy way is to put it in the drvPvt for the port. If an EOS is specified it looks for the eos on each read. It is started by the shell command:. This command should appear immediately after the command that initializes a port Some drivers provide configuration options to call this automatically.

This can be used to simulate flush processing for asynOctet if the port driver doesn't provide support for flush. It just reads and discards characters until no more characters arive before timeout seconds have occured. This support should be usable for a large class of low level register based drivers. For complicated devices other support is required. This release provides the following:. The callback is used in one of two ways:. These records are normally scanned periodically.

The registerInterruptUser callback is used to calculate an average value between record processes. A value is given to rval. Linear conversions are supported if the driver implements getBounds.

Linear conversions are supported if the driver properly implements getBounds. A value is given to val. Each time the record is processed a new value is read. It has support for both reading and writing a waveform. It does not support interrupt processing. The mask specified in the argument to asynMask is used in the calls to asymUInt32Digital methods.

In addition it is used to set the mask fields in bi and bo records and the mask and shft fields in mbbi, mbbo, mbbiDirect, and mbboDirect records. When the record is processed the saved value is put into rval. Support for drivers that implement interface asynOctet. The waveform support is similar to the string support. The waveform provides the following features not provided by the string support:.

A special record type asynRecord is provided. Details are described in asynRecord. This section provides a brief description of how to use it. The example creates a record with name "asynTest" formed from the concatenation of the P and R macros that will connect to port "L0" and addr Thus, a single record can be used to access all asyn devices connected to the IOC. Multiple records are only needed if one or more devices need a dedicated record.

The asynDriver distribution includes code to test asynDriver. It is also an example of how to interface to asynManager. It implements asynCommon and asynOctet. When asynOctet:write is called it saves the message. When asynOctet:read is called, the saved message is returned and the message is flushed.

In the example application it connects to echoDriver. An example where this technique might be used is a port driver for mult-drop serial that connects to a standard serial port.

It has device support for stringin records. The INP field has the syntax:. The stringOut record attaches to the device support supplied by asynOctetWriteRead. When the calcRecord is processed the following happens:. This starts two versions of echoDriver as port "A" and "B". For each of the three possible devices, the st. It also loads a set of records from asynRecord.

It starts one version of addrChangeDriver which connects to port A. It loads six versions of test. It provides gpib specific functions like SRQ handling.



0コメント

  • 1000 / 1000