008 - Extending process data using RPC transport

Content

Introduction

Beginning with version 2.1 of the module firmware it is possible for all protocol stacks to extend the possible process data size using RPC (Remote Procedere Call) transport. This feature allows significantly increasing the size of process data beyond the boundaries of the cyclic channel (73 Byte). However, process data using the RPC transport come with a significant cut in performance.

The cyclic channel provides up to 73 Byte, however in the direction of output data additionally a 4 byte generic data provider is mapped, which contains status information (LEDs, connection status, Update counter).

Features and Limitations

Using RPC transport limits the update cycle of process data, which is mapped to RPC, to a smaller value. Typically, an update cycle of around 100 ms is possible (see figure below). For objects, mapped to the data mapper, the update cycle (depending on the application controller (AC)) is 1 ms.

The amount of data, which can be transferred using RPC depends on the used hardware and communication stack.

For PROFINET the maximum data size is 1434 Byte per direction restricted by the stack itself.

For EtherCAT the theoretical maximum data size is 1408 Byte, but it’s limited by the available memory.

For EtherNet/IP the maximum data size is 505 Byte O->T and 509 Byte T->O of implicit messaging. For explicit messaging, the assembly size is limitited to 1492 Byte per assembly.

Even if the update cycle of the process data is larger because of the RPC transport, the typically cycle time per communication stack can still be achieved. The update cycle and the cycle time are independet from each other.

The update cycle for process data mapped to RPC depends on the amount of data required to update. Following table shows typical values where the amount of data is mapped to both communication directions (input data and output data) and all data is required to be updated in one cycle. The time required can reach 310 ms, see table below.

used module size per direction

average update cycle

used module size per direction

average update cycle

Octet string 1434 Byte

310 ms

Octet string 1024 Byte

230 ms

Octet string 512 Byte

125 ms

Octet string 256 Byte

70 ms

Octet string 128 Byte

40 ms

 

Please note: Access to the RPC objects is not allowed in data mapper callback context. Those objects need to be accessed in the main loop context (e.g. appl_loop()).

Application considerations

For all 3 communication stacks cyclic indication functions are available, which signal the update of process data or the request to update process data. In each case it is essential for operation of the module to keep processing as minimal as possible. Any extensive time consuming processing will affect the responsiveness and update cycle accuracy of the application. Following examples fulfil this requirement for PROFINET, EtherNet/IP and EtherCAT.

PROFINET:

GOAL_STATUS_T appl_setup( void ) { /* ... */ /* enable GOAL_PNIO_CB_ID_NEW_IO_DATA callback for each arrived cyclic frame */ goal_pnioCyclicCtrl(pPnio, GOAL_TRUE); /* ... */ } /****************************************************************************/ /** Profinet Callback Handler * * This function collects all callbacks from the stack and decides if the * callback must be handled. */ static GOAL_STATUS_T appl_pnioCb( GOAL_PNIO_T *pHdlPnio, /**< PROFINET handle */ GOAL_PNIO_CB_ID_T id, /**< callback id */ GOAL_PNIO_CB_DATA_T *pCb /**< callback parameters */ ) { GOAL_STATUS_T res = GOAL_OK; /* result */ uint8_t iops; /* IO producer status */ UNUSEDARG(pHdlPnio); /* handle callback IDs */ switch (id) { case GOAL_PNIO_CB_ID_NEW_IO_DATA: if (GOAL_TRUE != flgAppReady) { break; } /* read data from output module */ res = goal_pnioDataOutputGet(pPnio, APPL_API, APPL_SLOT_4, APPL_SLOT_4_SUB_1, dataDm, APPL_SIZE_13_SUB_1_OUT, &iops); if (GOAL_RES_OK(res)) { /* copy data to input module */ res = goal_pnioDataInputSet(pPnio, APPL_API, APPL_SLOT_3, APPL_SLOT_3_SUB_1, dataDm, APPL_SIZE_3_SUB_1_IN , GOAL_PNIO_IOXS_GOOD); } /* log info in case of an error */ if (GOAL_RES_ERR(res)) { goal_logErr("failed to mirror IO data [0x%"FMT_x32"]", res); } /* read data from output module */ res = goal_pnioDataOutputGet(pPnio, APPL_API, APPL_SLOT_2, APPL_SLOT_2_SUB_1, dataDm, APPL_SIZE_11_SUB_1_OUT, &iops); if (GOAL_RES_OK(res)) { /* copy data to input module */ res = goal_pnioDataInputSet(pPnio, APPL_API, APPL_SLOT_1, APPL_SLOT_1_SUB_1, dataDm, APPL_SIZE_1_SUB_1_IN, GOAL_PNIO_IOXS_GOOD); } /* log info in case of an error */ if (GOAL_RES_ERR(res)) { goal_logErr("failed to mirror IO data [0x%"FMT_x32"]", res); } break; } } }

 

EtherNet/IP:

/****************************************************************************/ /** EtherNet/IP Callback Handler * * This function collects all callbacks from the stack and decides if the * callback must be handled. */ GOAL_STATUS_T main_eipCallback( GOAL_EIP_T *pHdlEip, /**< GOAL Ethernet/ IP handle */ GOAL_EIP_CB_ID_T id, /**< callback id */ GOAL_EIP_CB_DATA_T *pCb /**< callback parameters */ ) { GOAL_STATUS_T res = GOAL_OK; /* return value */ UNUSEDARG(pHdlEip); UNUSEDARG(pCb); /* handle callback IDs */ switch (id) { case GOAL_EIP_CB_ID_ASSEMBLY_DATA_SEND: /* Inform the application about assembly object being sent next */ res = main_eipBeforeAssemblyDataSend( pHdlEip, pCb->data[0].instanceNr); break; case GOAL_EIP_CB_ID_ASSEMBLY_DATA_RECV: /* inform application on received data for an assembly object */ res = main_eipAfterAssemblyDataReceived( pHdlEip, pCb->data[0].instanceNr); break; default: break; } return res; }

 

EtherCAT:

/****************************************************************************/ /** EtherCAT Callback Handler * * This function collects all callbacks from the stack and decides if the * callback must be handled. * * @retval GOAL_OK successful * @retval other failed */ GOAL_STATUS_T appl_ecatCallback( GOAL_ECAT_T *pHdlEcat, /**< GOAL EtherCAT handle */ GOAL_ECAT_CB_ID_T id, /**< callback id */ GOAL_ECAT_CB_DATA_T *pCb /**< callback parameters */ ) { GOAL_STATUS_T res = GOAL_OK; /* result */ GOAL_MA_LED_T *pMaLed; /* LED ma handle */ switch (id) { case GOAL_ECAT_CB_ID_RxPDO_RECEIVED: appl_ecatPdoReceived(pHdlEcat); break; case GOAL_ECAT_CB_ID_TxPDO_PREPARE: appl_ecatPdoTxPrepare(pHdlEcat); break; default: res = GOAL_OK; break; } return res; }

 

Defining objects mapped to the RPC transport

PROFINET

The application decides whether the data mapper or RPC are used for transport of process data when submodule are plugged. Therefore 2 API functions, goal_pnioRpcSubmodPlug and goal_pnioDmSubmodPlug are available.

Plugging a submodule using data mapper transport:

 

Plugging a submodule using RPC transport:

Creating an object by generic function goal_pnioSubmodPlug is equivalent to goal_pnioDmSubmodPlug, causing a data transport by DM.

EtherCAT

The application decides weather data mapper or RPC is used for transport when objects are created. Therefore 2 API function, goal_ecatdynOdSubIndexDmAdd and goal_ecatdynOdSubIndexRpcAdd are available.

Creating an object with data mapper transport:

 

Creating an object with RPC transport:

Creating an object by generic function goal_ecatdynOdSubIndexAdd is equivalent to goal_ecatdynOdSubIndexDmAdd, causing a data transport by DM.

EtherNet/IP

The application decides weather data mapper or RPC is used for transport when objects are created. Therefore 2 API function, goal_eipCreateAssemblyObjectDm and goal_eipCreateAssemblyObjectRpc are available.

Creating an object with data mapper transport:

 

Creating an object with RPC transport:

Creating an assembly object by generic function goal_eipCreateAssemblyObject is equivalent to goal_eipCreateAssemblyObjectDm, causing a data transport by DM.

Accessing objects mapped to the RPC transport

As mentioned before, accessing the process data of RPC mapped objects should be handled carefully.

 

 

The following pattern should be used to access process data mapped to RPC. Following example shows handling of process data mapped to RPC for EtherCAT: