Moxa Protocol Converter Configuration and Programming Guide: Third Edition, June 2008
Moxa Protocol Converter Configuration and Programming Guide: Third Edition, June 2008
www.moxa.com/product
Copyright Notice
Trademarks
MOXA is a registered trademark of Moxa Inc.
All other trademarks or registered marks in this manual belong to their respective manufacturers.
Disclaimer
Information in this document is subject to change without notice and does not represent a commitment on the
part of Moxa.
Moxa provides this document “as is,” without warranty of any kind, either expressed or implied, including, but
not limited to, its particular purpose. Moxa reserves the right to make improvements and/or changes to this
manual, or to the products and/or the programs described in this manual, at any time.
Information provided in this manual is intended to be accurate and reliable. However, Moxa assumes no
responsibility for its use, or for any infringements on the rights of third parties that may result from its use.
This product might include unintentional technical or typographical errors. Changes are periodically made to the
information herein to correct such errors, and these changes are incorporated into new editions of the
publication.
Moxa Protocol Converter (referred to here as “MPC”) is a software program that runs on Moxa’s
ready-to-run embedded computers. MPC is an engine that loads custom programs called drivers.
The drivers audit bi-directional data streams between a network client and a serial device, or
between two serial devices.
The MPC engine implements a streamline architecture consisting of channels and drivers. A
channel is a logical path connecting two physical communication ports (serial or network). A
sequence of user-programmed drivers works in the middle to convert data from one protocol to
another or handle data processing tasks. The engine receives a data stream at one communication
port, assembles each data packet in the stream, and then passes the packets to the drivers for
processing. Each driver performs data formatting or conversion on the packet, as required. The
resulting packet is then passed to the next driver for further conversion. This process continues
until the final packet reaches the physical port at the other end of the channel.
One of the key benefits provided by MPC is that both serial and networking communication are
built into the engine. Without any additional programming on the part of the user, the engine alone
can perform transparent data transmission between any two communication ports (i.e., the data
channel mentioned above).
Another key benefit of MPC is that port-to-port communication is driver programmable. The
engine supports multiple drivers in a channel, which simplifies and modularizes the design of an
application that needs layers of data processing. In addition, most systems used in the field are
created by making minor changes to existing systems. With the MPC engine, these changes can be
achieved by either modifying a driver, or adding a driver to a channel.
Field Applications
Many industrial applications rely on a central system that monitors and controls a large number of
devices distributed around the site. In this case, control commands are handled by Remote
Terminal Units (RTUs) or Programmable Logic Controllers (PLCs), although many of the control
commands are issued by a centralized host housed in an operations center. Communication
between the different types of controllers can be carried out through a serial cable or over a LAN
(local area network).
Based on current practice, it is quite likely that embedded front-end computers will be installed at
field sites to provide a kind of store-and-forward mechanism. The embedded computers get raw
data, such as meter readings and device status reports, from the RTUs or PLCs, after which the
data is compiled and/or formatted as needed. The resulting data is transmitted to the host in the
operations room, and the operator generates control commands that are sent to the RTUs and
PLCs.
MPC Configuration and Programming Guide Introduction and Installation
The following figure indicates the general relationship between the host level, gateway level, and
device level.
Host Level
Gateway Level
Device Level
Moxa’s embedded computers act at the gateway level to acquire information from serial devices
and then report to the operators in the control room. The gateway can be used to send control
signals to devices through the serial links, and provide access by multiple clients over the local
network. The gateway can also be used to convert bi-directional data streams between serial
devices.
The gateways are used to allow serial and networking devices to communicate with each other.
Since a poorly designed system could require engineers to implement the same task over and over
again, there is a lot of motivation to find ways to streamline operations by reducing, or eliminating
altogether, the number of duplicate tasks that must be performed. MPC comes to the rescue in this
regard by consolidating common device communication tasks into a software engine, leaving the
task of developing drivers for various types of data conversion to programmers who are experts in
using the data formats and transmission protocols supported by the devices.
1-2
MPC Configuration and Programming Guide Introduction and Installation
A2B-stream
SERIAL
LAN
B2A-stream
Let’s look at the A2B-stream part of the streamline to illustrate how the process works. After
detecting the arrival of a data packet at port A, the channel passes it to the first driver for data
processing. After formatting the packet, the driver forwards the resulting data to the second driver.
The process proceeds in this way until the packet arrives at port B.
Each driver is comprised of at least two user-defined logic functions, with each of the functions
commanding data conversion for one side of the data stream. For example, in a MODBUS/TCP
driver, one function extracts and formats a MODBUS/TCP packet into a raw packet for the
A2B-stream, and another function extracts and formats a raw packet into a MODBUS/TCP packet
for the B2A-stream.
The MPC engine also allows two communication ports of the channel to be of the same type. One
example is a networking channel in which the receiving port is the same as the sending port.
Incoming data packets are sent back to the sender either with no formatting, or after being
formatted. Another example is a serial channel that has two different communication ports. Data
from a serial port will be relayed to another serial port, again either with no formatting, or after
being formatted.
1-3
2
Chapter 2 Configuration
After you install the software package on your development workstation, you will find several new
directories, as shown below, under the MPC directory.
Several driver examples are provided as a reference for programmers. The source code of the
drivers can be found in the “drvlib” directory. Also included in this directory is a “Makefile” file,
which can be used to compile all of the drivers in a Linux development workstation. To compile
WinCE drivers, use the eVC++ project files that are stored in the “drvlib_projects” directory.
The “release” directory contains the MPC programs mpc.exe and mpcdbg.exe. Sample
configuration files are stored in the “config_samples” sub-directory. In addition, executable
drivers are stored in the “drivers” sub-directory.
MPC is a user-space program. To install the program on the embedded computer, first create a
working directory. Next, use an ftp client to copy all the files and directories under the “release”
directory to this working directory.
The general format of the command used to invoke the MPC engine is:
mpc [-d config_path]
Use the “-d” option to specify the working directory, in which “config_path” is a full path. If you
run the program without specifying a configuration path, the MPC engine will assume that the
configuration file config.mpc is in the default directory, “/home/mpc” for Linux computers and
“/NORFlash/mpc” for WinCE computers.
MPC Configuration and Programming Guide Configuration
Configuration File—config.mpc
The configuration file is written in XML format, and consists of entries in text lines. The text is
NOT case sensitive. The following simple configuration example illustrates some of the features
of the protocol converter.
<MPC_DOC_ROOT>
<XPORTS>
<UART>
<MPC_PORT port="1" baud_rate="115200" data_bits="8" parity="None" stop_bits="1"
interface="RS232" flow_control="None" />
<MPC_PORT port="8" baud_rate="115200" data_bits="8" parity="None" stop_bits="1"
interface="RS232" flow_control="None" />
</UART>
<TCP_SERVER>
<MPC_PORT port="5001" max_connections="8" accepted_ips="" rt_timeout=”200” />
<MPC_PORT port="6001" max_connections="10" accepted_ips="" broadcast=”yes” />
</TCP_SERVER>
</XPORTS>
<XCHANNELS>
<MPC_CHANNEL name="CH1">
<PORT_A type="TCP_SERVER" port="5001" />
<PORT_B type="UART" port="1" />
<DRIVER name="D1" dll=“/home/mpc/mbtcp.dll” prefix="mbtcp" />
</MPC_CHANNEL>
<MPC_CHANNEL name="CH8">
<PORT_A type="TCP_SERVER" port="6001" />
<PORT_B type="UART" port="8" />
</MPC_CHANNEL>
</XCHANNELS>
</MPC_DOC_ROOT>
The entire file is enclosed by a document root, <MPC_DOC_ROOT></MPC_DOC_ROOT>. Two
major sections are enclosed by element pairs <XPORTS></XPORTS> and
<XCHANNELS></XCHANNELS>, respectively. The first pair defines communication ports of
different types. The second pair defines channels that are associated with the communication ports.
2-2
MPC Configuration and Programming Guide Configuration
</TCP_SERVER>
</XPORTS>
<XCHANNELS>
<MPC_CHANNEL name=“Modbus_TCP_RTU”>
<PORT_A type=“TCP_SERVER” port=“502” />
<PORT_B type=“UART” port=“1” />
<DRIVER name=“MBTCP” dll=“/home/mpc/mbtcp.dll” prefix=“mbtcp” />
<DRIVER name=“MBRTU” dll=“/home/mpc/mbrtu.dll” prefix=“mbrtu” />
</MPC_CHANNEL>
</XCHANNELS>
</MPC_DOC_ROOT>
TCP SERVER 502
SERIAL PORT #1
mbtcp.dll mbrtu.dll
The above example sets up a MODBUS TCP/RTU/RS485 channel between TCP server port 502
and serial port #1. The driver mbtcp.dll converts each MODBUS/TCP packet into raw data, and
then the driver mbrtu.dll assembles the data into a MODBUS/RTU packet. In the reverse direction,
the driver mbrtu.dll converts each MODBUS/RTU packet into raw data and then the driver
mbtcp.dll assembles the data into a MODBUS/TCP packet.
2-3
MPC Configuration and Programming Guide Configuration
SERIAL PORT #2
mbtcp.dll mbascii.dll
The above example sets up a MODBUS TCP/ASCII/RS485 channel between TCP server port
5001 and serial port #2. The driver mbtcp.dll converts each MODBUS/TCP packet into raw data
and then the driver mbascii.dll assembles the data into a MODBUS/ ASCII packet. In the reverse
direction, the driver mbascii.dll converts each MODBUS/ ASCII packet into raw data and then the
driver mbtcp.dll assembles the data into a MODBUS/TCP packet.
2-4
MPC Configuration and Programming Guide Configuration
SERIAL PORT #1
mbtcp.dll meter.dll mbrtu.dll
The driver meter.dll is inserted between the driver mbtcp.dll and driver mbrtu.dll.
IP addresses of embedded computers currently running MPC will be listed under “Group of
MPC.” Double click on the IP address of the device you would like to configure to invoke “Moxa
Protocol Converter.” Channels currently running in the embedded computer will be listed on the
main page.
The main page consists of a toolbar and a channel display. On the toolbar, there are several buttons
that allow users to create, save, and load configuration files. On the channel display, the serial
ports (the DB9 icon) are on the right side and Ethernet ports (the RJ45 icon) are on the left side.
2-5
MPC Configuration and Programming Guide Configuration
The number of serial port displayed is identical with that on the embedded computer. The Ethernet
ports are given by default. The number of Ethernets port is the same as the number of serial ports
on the embedded computer.
You will see a clear channel display page, with each icon showing a serial port or Ethernet port
with a “disabled” icon nearby.
2-6
MPC Configuration and Programming Guide Configuration
Step2: After configuring the serial port configuration, click “OK.” The Ethernet port can be set
up in a similar manner. Once you confirm the Ethernet port settings, the communication
channel configuration will be complete.
2-7
MPC Configuration and Programming Guide Configuration
Step3: Type a name for the channel in the “Configuring a Channel” window and then click
“OK.”
Configuring a Driver
To add a driver to a channel, right click on the communication channel and click on “Add driver.”
A configuration window pops up. Select the driver located in the mpc driver directory and input
the driver prefix string. The prefix is the special string defined in the driver function. If the driver
is a timer, you can provide the timer interval based on the direction the timer triggers data flow.
Ignore the timer interval setting if the driver is not a timer.
Setting Description
Path Specify the path of the driver object or the dynamic library.
Prefix The prefix is a short string used as a prefix in the name of the driver
function that the MPC engine calls. For example, the prefix mbtcp could be
used in the names of functions implemented by the driver. Examples of
possible function names are mbtcp_open_A2B, mbtcp_close_A2B,
mbtcp_exec_A2B, and mbtcp_exec_B2A.
Timer The timer_interval_A2B attribute, which is measured in milliseconds,
interval(A2B) should be defined if you implement a timer function (e.g.,
meter_timer_A2B) that the engine calls periodically. This timer is
particularly useful when an application needs to issue a request to a serial
port periodically. However, please note that every timer uses CPU resources,
so do not use a timer unless you really need it.
Timer The timer_interval_B2A attribute is similar to the timer_interval_A2B
interval(A2B) attribute. It should be defined if you implement a timer function (e.g.,
meter_timer_B2A) that the engine calls periodically.
2-8
MPC Configuration and Programming Guide Configuration
2-9
MPC Configuration and Programming Guide Configuration
the serial port, etc. If you do not need a timer, then don’t define
this attribute.
Max connections 4 Limits the number of concurrent clients that the server will
accept. The default value (4) will be used if this attribute is left
open.
Broadcast No Setting this attribute to yes will allow clients connected to the
same TCP server to share a response, regardless of which client
issued the request. For example, set the attribute to yes if one
client issues the control commands, and other clients simply
need to view the response.
Accepted IPs NA This option is used to grant access right to privileged clients
identified by their IP addresses. If this attribute is not defined,
then any client will be granted access. Setting the attribute to
172.16.2.0, for example, will cause the MPC engine to accept
clients with IP addresses ranging from 172.16.2.0 to
172.16.2.255. For multiple settings of this type, the IP addresses
should be separated by spaces.
2-10
MPC Configuration and Programming Guide Configuration
2-11
MPC Configuration and Programming Guide Configuration
2-12
MPC Configuration and Programming Guide Configuration
SERIAL PORT #1
mbtcp.dll mbrtu.dll
2-13
MPC Configuration and Programming Guide Configuration
The above example sets up a MODBUS TCP/RTU/RS485 channel between TCP server port 502
and serial port #1. The driver mbtcp.dll converts each MODBUS/TCP packet into raw data, and
then the driver mbrtu.dll assembles the data into a MODBUS/RTU packet. In the reverse direction,
the driver mbrtu.dll converts each MODBUS/RTU packet into raw data and then the driver
mbtcp.dll assembles the data into a MODBUS/TCP packet.
SERIAL PORT #2
mbtcp.dll mbascii.dll
The above example sets up a MODBUS TCP/ASCII/RS485 channel between TCP server port
5001 and serial port #2. The driver mbtcp.dll converts each MODBUS/TCP packet into raw data
and then the driver mbascii.dll assembles the data into a MODBUS/ ASCII packet. In the reverse
direction, the driver mbascii.dll converts each MODBUS/ ASCII packet into raw data and then the
driver mbtcp.dll assembles the data into a MODBUS/TCP packet.
SERIAL PORT #1
This driver meter.dll is inserted between driver mbtcp.dll and driver mbrtu.dll.
2-14
3
Chapter 3 MPC Driver Programming
We assume that you have installed either a Linux tool chain or Microsoft eVC++ 4.0 on your
development workstation. Linux drivers are in the format of executable shared objects, and
WinCE drivers are in the format of dynamic-link libraries. Note that the MPC engine does not
support computers that use the µcLinux operating system. This is because µcLinux does not
support shared objects.
The MPC engine is written in C, and for this reason, the drivers you create must also be written in
C. After compiling the drivers, the resulting driver files will be in the form of shared objects or
dynamic link libraries.
Note that your drivers use the same memory context as the MPC engine. For this reason, it is your
responsibility to use a “clean design” for your drivers. If your driver design is flawed, then code
violations of your drivers could cause a core dump of the MPC engine.
There is no need to use binary APIs when programming your drivers, but developers need to
follow the correct function definitions for a given x_driver.h file. Developers can make a copy of
this file, and then save it in a location accessible by your program.
After you install the software package on your development workstation, locate the “drvlib”
directory. In addition to containing the file x_driver.h, there are sub-directories used to store
sample code for drivers.
Structure DRVRPKT
The structure DRVRPKT is an I/O interface between the MPC engine, the caller, and a driver
function. Before calling this driver function, the engine prepares a data structure that describes the
content and the size of a data packet. The driver function processes the data packet, and provides
the content/size of the resulting data in the same data structure before ending the call.
typedef struct _DRVRPKT
{
unsigned char *packet_data;
unsigned int packet_size;
unsigned int packet_consumed;
void *private_data;
void *connection;
void *portA, *portB;
} DRVRPKT;
MPC Configuration and Programming Guide Service Information
Members
packet_data
Specifies the memory area for storing the data packet that is received by the engine and
passed to a driver function. Before handing process control back to the engine, the driver
function must assign another malloc or static area that stores the resulting data packet.
packet_size
Specifies the size of the data packet that packet_data initially points to. Before ending its
call, a driver function must specify it to be the size of the resulting data. Setting the value to
zero means it will stop forwarding the data packet to another driver.
packet_consumed
A driver function must specify the number of bytes that are consumed in the original packet.
With this information, the engine is informed to remove the data to be processed. This
value is initially equal to the number of bytes of the original data packet.
private_data
A driver function must specify the number of bytes that are consumed in the original packet.
With this information, the engine is informed to remove the data to be processed. This
value is initially equal to the number of bytes of the original data packet.
connection
Specifies the handle of an open connection associated with the communication port which
data packets are received from and sent to.
portA and portB
Specify two pointers to the two end ports of the underlying channel.
Driver Functions
A driver is composed of driver functions prefixed by a string (xxx, for example). The driver has
the option to implement each of the following functions.
int xxx_driver_init(void);
void xxx_driver_release(void);
int xxx_open_A2B(DRVRPKT *pktX, unsigned int *timer_interval);
int xxx_open_B2A(DRVRPKT *pktX, unsigned int *timer_interval);
void xxx_close_A2B(DRVRPKT *pktX);
void xxx_close_B2A(DRVRPKT *pktX);
int xxx_exec_A2B(DRVRPKT *pktX);
int xxx_exec_B2A(DRVRPKT *pktX);
int xxx_timer_A2B(DRVRPKT *pktX, unsigned int *timer_interval);
int xxx_timer_B2A(DRVRPKT *pktX, unsigned int *timer_interval);
The function xxx_driver_init is called when the associated channel is established. In this function,
you can execute global parameter initialization, memory allocation, and etc. On the other hand, the
function xxx_driver_release is called when the program exits and the associated channel must be
released.
The function xxx_open_A2B/xxx_open_B2A is called when an open connection is set up at one
end (port A/B) of the channel.
int xxx_open_A2B(DRVRPKT *pktX, unsigned int *timer_interval);
int xxx_open_B2A(DRVRPKT *pktX, unsigned int *timer_interval);
3-2
MPC Configuration and Programming Guide Service Information
Parameters
pktX
It is a pointer to a structure DRVRPKT. Its member connection specifies the handle of the
open connection. The function normally assigns the address of an allocated memory space
to its member private_data. The memory will be referenced when the following functions
are executed. A NULL value can be assigned if the reference is of no importance.
timer_interval
If the function specifies a value (in milliseconds) to this parameter and the driver has
defined the timer function xxx_timer_A2B/xxx_timer_B2A, the engine would periodically
call the timer function.
Return Values
If the function has allocated memory successfully, it returns MPC_DRV_OK. Otherwise,
it returns MPC_DRV_FAIL, and the MPC engine closes the connection accordingly.
Example
int
rfc2217_open_A2B(DRVRPKT *pktB, unsigned int *timer_interval)
{
pktB->private_data = calloc(1, 256);
if (pktB->private_data)
return MPC_DRV_OK;
else
return MPC_DRV_FAIL;
}
If the driver needs to respond the established connection with data, it should store the data on the
allocated memory, assign packet_data and packet_size of pktX, and return the function with the
symbolic constant MPC_DRV_ BACKWARD.
The function xxx_close_A2B/xxx_close_B2A is implemented when the open connection is broken
at one end (port A/B) of the channel. Normally, this function frees up the allocated memory
pointed to by the member private_data of a structure DRVRPKT.
void xxx_close_A2B(DRVRPKT *pktX);
void xxx_close_B2A(DRVRPKT *pktX);
Example
void
rfc2217_close_A2B(DRVRPKT *pktB)
{
if (pktB->private_data) free(pktB->private_data);
}
The function xxx_exec_A2B is called each time a data packet is passed from port A to this driver.
In contrast, the function xxx_exec_B2A handles data packets in the reverse direction. Use the
following formats to implement these functions:
int xxx_exec_A2B(DRVRPKT *pktX);
int xxx_exec_B2A(DRVRPKT *pktX);
3-3
MPC Configuration and Programming Guide Service Information
Parameters
pktX
It is a pointer to a structure DRVRPKT. Before the function is called, the engine prepares
the structure body DRVRPKT pointed to by the argument pktX. Member private_data
points to the memory space allocated in function xxx_open_A2B or xxx_open_B2A.
Member packet_data points to the data packet, and member packet_size is the length of
the data packet. In addition, member packet_consumed has the same value as member
packet_size. This implies that the engine assumes that the function consumes the whole
packet.
After processing the data, the function is responsible for pointing member packet_data to
the memory area (normally member private_data) that stores the resulting data, and
specify the length of it in member packet_size. If the function decides not to forward data
to the next driver, it sets packet_size to zero. Furthermore, this function must specify
member packet_consumed to be the length of the data being consumed, and informs the
engine to remove the processed data.
Return Values
This function returns one of the following symbolic constants:
y MPC_DRV_FORWARD – indicates that the driver has processed data successfully
and asks the engine to keep forwarding the resulting data packet.
y MPC_DRV_ BACKWARD – indicates that the driver has processed data successfully
and asks the engine to pass the resulting data packet in the reverse direction.
y MPC_DRV_ FAIL – indicates that the driver has stopped forwarding the data packet.
Each driver has the option to implement two timer functions, xxx_timer_A2B and xxx_timer_B2A.
They are called by the engine periodically.
void xxx_timer_A2B(DRVRPKT *pktX, unsigned int *timer_interval);
void xxx_timer_B2A(DRVRPKT *pktX, unsigned int *timer_interval);
Parameters
pktX
It is a pointer to a structure DRVRPKT. Member private_data points to the memory space
allocated in function xxx_open_A2B or xxx_open_B2A. The function uses member
packet_data and packet_size of pktX to forward data.
timer_interval
This parameter specifies the time interval (in milliseconds) between each call. Before
ending the call, the function can change the timer interval of the timer.
Remarks
The main role of a timer function is normally to generate a data query, and asks the engine
to relay the data to the next driver or a target port.
Example
int
mbrtu_timer_A2B(DRVRPKT *pkt, unsigned int *timer_in)
{
unsigned char *buffer;
3-4
MPC Configuration and Programming Guide Service Information
pkt->packet_size = 6;
pkt->packet_data = buffer;
return MPC_DRV_FORWARD;
}
EXEC=dxxx.dll
CFLAGS=-Wall -fPIC
LINK=$(CC) -shared -Wl,-soname,$(EXEC) -o $@
LIBS=
# add objects
OBJS= dxxx.o
DEPS=
all: $(EXEC)
$(EXEC): $(OBJS) $(DEPS)
$(LINK) $(OBJS) $(LIBS)
clean:
rm -f *.o $(EXEC)
3-5
MPC Configuration and Programming Guide Service Information
2. In the pop-up window, select WCE Dynamic-Link Library. Enter a project name and then
click OK.
3-6
MPC Configuration and Programming Guide Service Information
5. On the eVC++ 4.0 menu bar, click Project Æ Add to Project Æ Files to add source files to
the project. Remember to add an empty file, dxxx.def.
3-7
MPC Configuration and Programming Guide Service Information
7. Edit the file dxxx.def. Behind the keyword LIBRARY in the first line, specify the name of
the dll, dxxx for example. Add the keyword EXPORTS in the second line, and then add the
function names of the driver, as shown below
3-8