Background
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; }
LOM Codesnippet an cifx api anpassen
Sie müssen die Paketsendefunktion noch folgender anpassen, da sie aus einem LOM Beispiel sind.
/* 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);