Background
As mandatory element, each EtherCAT slave has a slave information interface (SII) which is accessible by the slave.
Physically, this is a special storage area for slave-specific data in an EEPROM memory chip. Its size is varaiable in the range of 1 kBits – 512 kBits (128 – 65536 Bytes).
For loadable firmware, the size of the SII is limited to 64 K. Because there is no separate EEPROM in the netX chips, the SII is virtually created in the netX.
After configuration, the firmware writes the content of the SII to the virtual EEPROM.
In case the application has created a custom object dictionary, the EtherCAT Slave does not have enough information to write the whole SII image.
In this case, the application has to write the SII data starting from address 0x80 using the SII related funtions at every startup of the device.
Please find more informations about the SII in the EtherCAT Slave Protocol API:
https://kb.hilscher.com/display/DL/EtherCAT+Slave
Create an SII image
With the help of the Conformance Test Tool (CTT) or TwinCAT, an SII image can be created from an ESI file.
Please first of all delete the RX/TX-PDO blocks from the ESI file, since the CTT and Twincat can only read a maximum of 0xFF "String category blocks". They are also not needed to create an SII image.
Please follow these steps, in case you are using the Conformance Test Tool for creation of an SII image:
- Open the Conformance Test Tool.
- Scan for any device and open the SII tab.
- Select the ESI file from the tab on the right side "ESI Files Repository" and add it to the SII tab via drag and drop.
- This can be saved in a *.BIN file now.
- Open the *.BIN file in an Hexeditior öffnen.
- Delete every entry before address 0x080 (first 128 bytes). This area will we written by the stack and is therefore not needed.
- change the *.BIN file to a *.c formatted file.
Write the SII image
The follow process needs to be performed, between the Channel Init state and "Bus on".
Therefore the Bus Startup should be changed from "Automatic" to "Controlled by Application".
This is how it needs to be configured in Sycon.net (other configuration Tools may vary):
After getting the configuration "RCX_CHANNEL_INIT_CNF", call the function "Sii_SetupCategoryData()".
Code snippet LOM
const TLR_UINT8 g_abSiiCategoryData []= { 0x0A, 0x00, 0x94, 0x00, … /*Please copy the data from the SII which has been created out of the ESI file here. Remember not to use the first 128 Byte!*/ }; const unsigned long g_ulSiiCategoryDataSize = sizeof(g_abSiiCategoryData); /******************************************************************************* * @brief This function creates a valid SII image for the slave. * It uses packets to copy the binary image of the category data into * the SII. * * @param ptRsc pointer to resources. * @param pbCategoryData pointer to image of category data according * to EtherCAT specification. * @param ulCategoryDataBytelen byte length of category data array * * @return TLR_RESULT returns TLR_S_OK if no error, * otherwise it will return an error code. */ TLR_RESULT Sii_SetupCategoryData( ECSPX_RSC_T* ptRsc, const TLR_UINT8* pbCategoryData, TLR_UINT32 ulCategoryDataBytelen) { TLR_RESULT eRslt = TLR_S_OK; ECAT_ESM_SII_WRITE_REQ_T* ptSiiWriteReq = NULL; void* pvPck = NULL; TLR_UINT32 ulImagePos = 0; TLR_UINT32 ulFragmentLen = 0; /* we start at position 0 of the image */ ulImagePos = 0x00; while (ulImagePos < ulCategoryDataBytelen) { /* by default we write 0x10 byte fragments */ ulFragmentLen = 0x10; /* check if our end position is larger than the image of the category data */ if (ulImagePos + ulFragmentLen > ulCategoryDataBytelen) { ulFragmentLen = ulCategoryDataBytelen - ulImagePos; } /* retrieve a pointer to a resource (packet) of pool */ eRslt = TLR_POOL_PACKET_GET(ptRsc->tLoc.hPool, &pvPck); if (eRslt != TLR_S_OK) { /* leave loop */ break; /* TODO: improve */ } /* write the fragment */ ptSiiWriteReq = (ECAT_ESM_SII_WRITE_REQ_T*)pvPck; memset(ptSiiWriteReq, 0, sizeof(ECAT_ESM_SII_WRITE_REQ_T)); /* fill packet header */ ptSiiWriteReq->tHead.ulDest = (UINT32)ptRsc->tRem.tEcsEsmTaskQueLink.hQue; ptSiiWriteReq->tHead.ulSrc = (UINT32)ptRsc->tLoc.hQue; ptSiiWriteReq->tHead.ulDestId = 0x00; ptSiiWriteReq->tHead.ulSrcId = 0x00; ptSiiWriteReq->tHead.ulLen = 4 + ulFragmentLen; ptSiiWriteReq->tHead.ulId = 0x00; ptSiiWriteReq->tHead.ulSta = TLR_S_OK; ptSiiWriteReq->tHead.ulCmd = ECAT_ESM_SII_WRITE_REQ; ptSiiWriteReq->tHead.ulExt = 0x00; ptSiiWriteReq->tHead.ulRout = 0x00; /* fill data part of packet */ ptSiiWriteReq->tData.ulOffset = ulImagePos + 0x80; /* category data starts at 0x80 of SII */ memcpy((char*)(&ptSiiWriteReq->tData.abData), pbCategoryData + ulImagePos, ulFragmentLen); /* fire the request */ eRslt = TLR_QUE_SENDPACKET_FIFO_INTERN(ptRsc->tRem.tEcsEsmTaskQueLink.hQue, ptSiiWriteReq, TLR_INFINITE); /* TODO: TLR_QUE_SENDPACKET_FIFO */ /* TODO: why not TLR_FINITE ? */ if ( eRslt != TLR_S_OK ) { eRslt = TLR_POOL_PACKET_RELEASE( ptRsc->tLoc.hPool, ptSiiWriteReq ); /* leave loop */ break; } /* we wait directly for expected cnf packet */ eRslt = WaitForResponse( ptRsc, (ptSiiWriteReq->tHead.ulCmd | 1) ); /* TODO: improve !! */ if ( eRslt != TLR_S_OK ) { /* leave loop */ break; /* TODO: improve ? */ } /* set next start position */ ulImagePos += ulFragmentLen; } /* check if error occured */ if ( eRslt != TLR_S_OK ) { TODO: add error handling */ } return eRslt; }
Change the LOM Codesnippet to fit the CIFX API
The paket send function needs to be changed as shown below for use in CIFX API, sind the above codesnipped has been created for LOM Firmware only.
/* packet for sending */ /*__ALIGN4_PRE CIFX_PACKET __ALIGN4_POST tSendPkt = {{0}};*/ CIFX_PACKET tSendPkt = {{0}}; /* packet for writing station alias to SII * (CRC checksum will be calculated and set by stack) */ ECAT_ESM_SII_WRITE_REQ_T* ptWriteSiiReq = (ECAT_ESM_SII_WRITE_REQ_T*)&tSendPkt; ptSiiWriteReq->tHead.ulDest = 0x20; ptSiiWriteReq->tHead.ulSrc = 0; /* fire the request */ tResult = xChannelPutPacket(ptCoEApp->tCommon.hChannel, (CIFX_PACKET*)ptWriteSiiReq, ptCoEApp->tCommon.ulTimeout);