- /* the last SDO is still in work */
- return MBXERR_SERVICEINWORK;
- }
- #endif
- /*根据SDO的不同的服务类型,选择想对应的SDO服务*/
- switch (command)
- {
- case SDOSERVICE_INITIATEDOWNLOADREQ:
- case SDOSERVICE_INITIATEUPLOADREQ:
- /* the variable index contains the requested index of the SDO service */
- /*这个变量索引包含需要的SDO服务的索引*/
- index = pSdoInd->SdoHeader.Sdo[SDOHEADER_INDEXHIOFFSET] & SDOHEADER_INDEXHIMASK;
- index <<= 8;
- index += pSdoInd->SdoHeader.Sdo[SDOHEADER_INDEXLOOFFSET] >> SDOHEADER_INDEXLOSHIFT;
- /* the variable subindex contains the requested subindex of the SDO service */
- <span style="white-space:pre"> </span>/*子索引的变量包含需要的SDO服务需要的子索引*/
- subindex = pSdoInd->SdoHeader.Sdo[SDOHEADER_SUBINDEXOFFSET] >> SDOHEADER_SUBINDEXSHIFT;
- /* OBJ_GetObjectHandle checks if the requested index is defined in the object dictionary */
- <span style="white-space:pre"> </span>/*OBJ_GetObjectHandle检查是否需要的index是否在对象字典里面定义,并获得它的句柄*/
- pObjEntry = OBJ_GetObjectHandle( index );
- if ( pObjEntry )
- {
- <span style="white-space:pre"> </span> /*如果在搜寻所有的对象字典之后,得到所需要索引的句柄*/
- /* transferType contains the information if the SDO Download Request or the SDO Upload Response
- can be an expedited service (SDO data length <= 4, that means the data is stored in the
- SDO-Header completely */
- <span style="white-space:pre"> </span> /*transferType包含那些信息,是否SDO 下载请求和SDO 上传响应可以是快速服务类型(SDO数据长度小于等于4个字节,数据可以完全放在SDO-Header里面)*/
- UINT8 bTransferType = 0;
- /* pData is the pointer to the received (SDO-Download) or sent (SDO-Upload) SDO data in the mailbox */
- <span style="white-space:pre"> </span> /*pData是一个指针指向在邮箱里面,SDO下载和SDO上传的对象字典的数据*/
- UINT16 MBXMEM * pData = NULL;
- #if SEGMENTED_SDO_SUPPORTED
- UINT8 segTransfer = 0;
- #endif
- {
- dataSize = objLength = OBJ_GetObjectLength( index, subindex, pObjEntry, (UINT8) (sdoHeader & SDOHEADER_COMPLETEACCESS) );
- if ( command == SDOSERVICE_INITIATEUPLOADREQ )//如果SDO里面的命令是SDO上传请求的话
- {
- <span style="white-space:pre"> </span>/*如果SDO里面的对象字典的长度小于等于MAX_EXPEDITED_DATA和不等于零的时候,则是快速类型的上传模式*/
- /* SDO Upload */
- if ( mbxSize != EXPEDITED_FRAME_SIZE )
- /* a SDO Upload request has always a fixed size (2 Byte CoE-Header plus 8 Byte SDO-Header) */
- return MBXERR_INVALIDSIZE;
- /* distinguish between expedited and normal upload response within the length of the response data */
- if ( (objLength <= MAX_EXPEDITED_DATA) && objLength != 0 )
- {
- /* Expedited Upload */
- bTransferType = 1;
- /* pData is the pointer where the object data has to be copied for the response */
- <span style="white-space:pre"> </span>/*pData是一个指针,它指向的对象字典数据被复制对应的数据作为响应*/
- pData = ((TINITSDOUPLOADEXPRESMBX MBXMEM *) pSdoInd)->Data;
- /* initialize the 4 data bytes of the SDO upload response because the requested object data
- could be less than 4 */
- <span style="white-space:pre"> </span>/*因为请求的对象数据是小于4个字节,初始化4个字节数据给SDO上传响应*/
- pData[0] = 0;
- pData[1] = 0;
- }
- else<span style="white-space:pre"> </span>//这个else是对应上面的((objLength<=MAX_EXPEDITED_DATA)&& objLength !=0) 如果对象字典的长度大于MAX_EXPEDITED_DATA也就是4个字节的时候。则说明上传是分段上传模式或者是正常上传模式。
- {
- dataSize = u16SendMbxSize - MBX_HEADER_SIZE - UPLOAD_NORM_RES_SIZE;
- <span style="white-space:pre"> </span>/*如果对象字典的长度比邮箱对象数据区的长度还要打的时候,说明是要采用分段类型的形式上传数据*/
- if ( dataSize < objLength )
- /* Segmented Upload */
- segTransfer = 1;
- else
- :pre"> </span>/*否则采用正常上传模式*/
- /* Normal Upload */
- pData = ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data;
- <span style="white-space:pre"> </span> /*pData指向对象字典的数据区地址*/
- #else/*如果从站本身不支持分段上传模式的话,则不需要上面的判断*/
- /* Normal Upload */
- /* pData is the pointer where the object data has to be copied for the response */
- <span style="white-space:pre"> </span>/*pData是一个指针,作为响应,指向的地方对象字典的数据应该被拷贝*/
- pData = ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data;
- #endif
- }
- }
- else//如果对象字典的命令,不是SDO上传命令的话
- {
- /* SDO-Download: store if the request is a expedited or normal request 判断是否为快速还是普通请求 */
- bTransferType = sdoHeader & SDOHEADER_TRANSFERTYPE;
- }
- }
- if ( command == SDOSERVICE_INITIATEDOWNLOADREQ )//如果SDO的命令是下载请求
- {
- /* SDO Download */
- if ( bTransferType )//根据前面判断是否为快速下载请求
- {
- /* Expedited Download */
- if ( mbxSize != EXPEDITED_FRAME_SIZE )
- /* an Expedited SDO Download request has always a fixed size (2 Byte CoE-Header plus 8 Byte SDO-Header) */
- return MBXERR_INVALIDSIZE;
- /* dataSize gets the real size of the downloaded object data (1,2,3 or 4) */
- dataSize = MAX_EXPEDITED_DATA - ((sdoHeader & SDOHEADER_DATASETSIZE) >> SDOHEADERSHIFT_DATASETSIZE);
- /* pData is the pointer to the downloaded object data */
- <span style="white-space:pre"> </span> //pData是一个指针指向SDO的数据区
- pData = (UINT16 MBXMEM *) &pSdoInd[1];
- }
- else//如果不是快速下载请求
- {
- /* Normal Download */
- /* downloadSize gets the real size of the downloaded data */
- /* '&' operator was too much */
- UINT32 downloadSize = ((UINT32)(SWAPWORD(((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->CompleteSize[1]))<<16) + (SWAPWORD(((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->CompleteSize[0]));
- /* HBu 29.03.06: if it is a segmented download the mbxSize has to be the complete mailbox size */
- if ( (MBX_HEADER_SIZE+EXPEDITED_FRAME_SIZE+downloadSize) > u16ReceiveMbxSize )//如果它是一个分段下载类型,mbxSize毕业是一个完整的邮箱长度
- {
- if ( mbxSize != (u16ReceiveMbxSize-MBX_HEADER_SIZE) )
- return MBXERR_INVALIDSIZE;
- }
- else
- {
- if ( mbxSize != (EXPEDITED_FRAME_SIZE+downloadSize) )
- /* the mbxSize and the downloadSize are not consistent (mbxSize = downloadSize + 2 byte CoE-Header + 8 byte SDO Header */
- return MBXERR_INVALIDSIZE;
- }
- /* pData is the pointer to the downloaded object data */
- pData = (UINT16 MBXMEM *) ((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->Data;//pData是一个指针指向下载对象的数据区
- /* the received dataSize will be checked in the object specific functions called from
- OBJ_Write (in objdef.c) */
- dataSize = downloadSize;接受的dataSize多大将会被检查在对象特殊的函数,在OBJ_Write(在object.c文件里调用)
- if ( dataSize > (UINT32)(mbxSize - DOWNLOAD_NORM_REQ_SIZE) )//对象字典的长度大于mbxSize-DOWNLOAD_NORM_REQ_SIZE的时候
- #if SEGMENTED_SDO_SUPPORTED
- /* Segmented Download */
- segTransfer = 1;//采用分段下载的形式
- #else /* SEGMENTED_SDO_SUPPORTED */
- abort = ABORTIDX_PARAM_LENGTH_ERROR;
- #endif /* SEGMENTED_SDO_SUPPORTED */
- }
- }
- if ( sdoHeader & SDOHEADER_COMPLETEACCESS )//接下来对sdoHeader的是否完全操作进行判断
- #if COMPLETE_ACCESS_SUPPORTED
- {
- bCompleteAccess = 1;//可以完全操作
- // HBu 02.05.06: Complete Access is only supported with subindex 0 and 1
- if (subindex > 1)
- abort = ABORTIDX_UNSUPPORTED_ACCESS;
- }
- #else
- abort = ABORTIDX_UNSUPPORTED_ACCESS;
- #endif
- if ( abort == 0 )//abort ==0,说明是可以完全操作子索引是0或者1
- {
- #if SEGMENTED_SDO_SUPPORTED
- if ( segTransfer )//如果可以分段传输
- {
- bSdoSegFollows = TRUE;
- bSdoSegLastToggle = 1;
- #if COMPLETE_ACCESS_SUPPORTED
- bSdoSegAccess = bCompleteAccess;
- #endif
- nSdoSegIndex = index;
- nSdoSegSubindex = subindex;
- pSdoSegObjEntry = pObjEntry;
- if ( command == SDOSERVICE_INITIATEUPLOADREQ )
- nSdoSegCompleteSize = objLength;
- else
- nSdoSegCompleteSize = dataSize;
- if (pSdoSegData != NULL)
- {
- FREEMEM( (UINT16 VARMEM *) pSdoSegData);
- pSdoSegData = NULL;
- }
- /*ECATCHANGE_START(V5.01) MBX1*/
- pSdoSegData = (UINT16 VARMEM *) ALLOCMEM( ROUNDUPBYTE2WORD(nSdoSegCompleteSize) );
- /*ECATCHANGE_END(V5.01) MBX1*/
- if ( pSdoSegData == NULL )
- abort = ABORTIDX_OUT_OF_MEMORY;
- else
- {
- if ( command == SDOSERVICE_INITIATEUPLOADREQ )
- {
- /* Segmented Upload */
- abort = OBJ_Read( index, subindex, objLength, pObjEntry, (UINT16 MBXMEM *) pSdoSegData, bCompleteAccess );
- <span style="white-space:pre"> </span>//如果读操作成功的话,则返回0;如果读操作失败的话,则返回0xFF
- if ( abort == 0 )
- {
- MBXMEMCPY( ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data, pSdoSegData, dataSize );//将读到的pSdoSegData数据拷贝到pSdoInd的数据区。
- nSdoSegService = SDOSERVICE_UPLOADSEGMENTREQ;
- }
- #if SDO_RES_INTERFACE
- else if ( abort == ABORTIDX_WORKING )
- {
- /* ECATCHANGE_START(V5.01) SDO6*/
- /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) */
- //在这种情况应用程序产生一个SDO-Response通过调用函数SDOS_SdoRes()就是SDO响应程序,当数据对象接入函数已经被定义
- u8PendingSdo = SDO_PENDING_SEG_READ;
- bStoreCompleteAccess = bCompleteAccess;
- u8StoreSubindex = subindex;
- u16StoreIndex = index;
- u32StoreDataSize = objLength;
- pStoreData = pSdoSegData;
- pSdoPendFunc = pObjEntry->Read;//采用虚函数的形式定义数据对象的函数
- bSdoInWork = TRUE;
- /* we have to store the buffer and the response header */
- pSdoResStored = pSdoInd;
- /*update command field*/
- pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] &= ~SDOHEADER_COMMANDMASK;
- pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= (sdoHeader & (SDOHEADER_COMPLETEACCESS | SDOHEADER_COMMAND));
- nSdoSegService = SDOSERVICE_UPLOADSEGMENTREQ;
- return 0;//返回去函数,并且,通过SDOS_SdoRes()来操作数据对象
- /* ECATCHANGE_END(V5.01) SDO6*/
- }
- #endif
- }
- else//如果命令是SDO下载命令,则将pSdoInd->Data里面的数据拷贝到pSdoSegData里面,并且,付对应的SdoSegService和对应的数据长度
- {
- /* Segmented Download */
- MBXMEMCPY( pSdoSegData, ((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->Data, mbxSize-DOWNLOAD_NORM_REQ_SIZE );
- nSdoSegService = SDOSERVICE_DOWNLOADSEGMENTREQ;
- dataSize = (mbxSize-DOWNLOAD_NORM_REQ_SIZE);
- }
- nSdoSegBytesToHandle = dataSize;
- }
- }
- else//接下来的这种情况,考虑不是分段传输的情况
- #endif // SEGMENTED_SDO_SUPPORTED
- {
- #if SEGMENTED_SDO_SUPPORTED
- #if SDO_RES_INTERFACE
- if ( objLength == 0 )
- {
- /* the objLength is not known, therefore the variables for a possible segmented transfer
- should be initialized */
- nSdoSegIndex = index;
- nSdoSegSubindex = subindex;
- pSdoSegObjEntry = pObjEntry;
- }
- #endif // SDO_RES_INTERFACE
- #endif // SEGMENTED_SDO_SUPPORTED
- if ( command == SDOSERVICE_INITIATEUPLOADREQ )//如果SDO服务是上传服务
- {
- /* Expedited or Normal Upload *///已经排除了分段上传,就剩下快速上传和普通上传模式
- abort = OBJ_Read( index, subindex, objLength, pObjEntry, pData, bCompleteAccess );
- #if SDO_RES_INTERFACE
- if ( abort == ABORTIDX_WORKING )
- {
- /* ECATCHANGE_START(V5.01) SDO6*/
- /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) *///同上的分段上传的情况
- u8PendingSdo = SDO_PENDING_READ;
- bStoreCompleteAccess = bCompleteAccess;
- u8StoreSubindex = subindex;
- u16StoreIndex = index;
- u32StoreDataSize = objLength;
- pStoreData = pData;
- pSdoPendFunc = pObjEntry->Read;
- bSdoInWork = TRUE;
- /* we have to store the buffer and the response header */
- pSdoResStored = pSdoInd;
- /*update command field*/
- pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] &= ~SDOHEADER_COMMANDMASK;
- pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= (sdoHeader & (SDOHEADER_COMPLETEACCESS | SDOHEADER_COMMAND));
- return 0;
- /* ECATCHANGE_END(V5.01) SDO6*/
- }
- #endif // SDO_RES_INTERFACE
- }
- else
- {
- /* Expedited or Normal Download *///快速和普通下载模式
- abort = OBJ_Write( index, subindex, dataSize, pObjEntry, pData, bCompleteAccess );
- #if SDO_RES_INTERFACE
- if ( abort == ABORTIDX_WORKING )
- {
- /* ECATCHANGE_START(V5.01) SDO6*/
- /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) */
- u8PendingSdo = SDO_PENDING_WRITE;
- bStoreCompleteAccess = bCompleteAccess;
- u8StoreSubindex = subindex;
- u16StoreIndex = index;
- u32StoreDataSize = dataSize;
- pStoreData = pData;
- pSdoPendFunc = pObjEntry->Write;
- bSdoInWork = TRUE;
- /* we have to store the buffer and the response header */
- pSdoResStored = pSdoInd;
- /*update command field*/
- pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] &= ~SDOHEADER_COMMANDMASK;
- pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= (sdoHeader & (SDOHEADER_COMPLETEACCESS | SDOHEADER_COMMAND));
- return 0;
- /* ECATCHANGE_END(V5.01) SDO6*/
- }
- #endif // SDO_RES_INTERFACE
- }
- } /* else if ( objLength == 0 ) */
- } /* if ( abort == 0 ) */
- }//endif 获得不到对应的对象字典的句柄
- else
- {
- abort = ABORTIDX_OBJECT_NOT_EXISTING;
- }
- break;
- #if SEGMENTED_SDO_SUPPORTED
- case SDOSERVICE_DOWNLOADSEGMENTREQ://当SDOSERVICE_DOWNLOADSEGMENTREQ和SDOSERVICE_UPLOADSEGMENTREQ产生时候一并在下面处理
- case SDOSERVICE_UPLOADSEGMENTREQ:
- if ( command == nSdoSegService )
- {
- if ( command == SDOSERVICE_DOWNLOADSEGMENTREQ )
- abort = SdoDownloadSegmentInd( (TDOWNLOADSDOSEGREQMBX MBXMEM *) pSdoInd );
- <span style="white-space:pre"> </span>//这个函数将会被调用当下载SDO主站的分段请求服务,如果它是最后一个分段数据的话,将会被写入到对象字典,这个函数自身会做出对象响应
- else
- abort = SdoUploadSegmentInd( (TUPLOADSDOSEGREQMBX MBXMEM *) pSdoInd );
- }
- else
- abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
- break;
- #endif
- default:
- abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
- break;
- }
- #if SDO_RES_INTERFACE
- /* ECATCHANGE_START(V5.01) SDO6*/
- if(abort != ABORTIDX_WORKING)
- /* ECATCHANGE_END(V5.01) SDO6*/
- #endif
- {
- /*当SDO响应应该被发送的时候,这个函数将会被调用*/
- SdoRes(abort, command, (UINT8) (sdoHeader & SDOHEADER_COMPLETEACCESS), (UINT16) dataSize, objLength, pSdoInd);
- }
- return 0;
- }