往死里写——SDO处理过程2-1

来源:互联网 发布:lua5.3 windows 下载 编辑:程序博客网 时间:2024/04/29 23:40
UINT8 SDOS_SdoInd(TINITSDOMBX MBXMEM *pSdoInd){    UINT8 abort = 0;    UINT8 sdoHeader = pSdoInd->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] & SDOHEADER_COMMANDMASK;    /* the SDO-command is in bit 5-7 of the first SDO-Byte */    UINT8 command = (sdoHeader & SDOHEADER_COMMAND);    /* mbxSize contains the size of the mailbox (CoE-Header (2 Bytes) + SDO-Header (8 Bytes) + SDO-Data (if the data length is greater than 4)) */    UINT16 mbxSize = pSdoInd->MbxHeader.Length;    UINT16 index;    UINT8 subindex;    OBJCONST TOBJECT OBJMEM * pObjEntry;    /* this variable contains the information, if all entries of an object will be read (bCompleteAccess > 0) or a single entry */    UINT8 bCompleteAccess = 0;    UINT32 objLength = 0;    UINT32 dataSize = 0;#if SDO_RES_INTERFACE    if ( bSdoInWork )    {        /* 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 */
/*子索引的变量包含需要的SDO服务需要的子索引*/        subindex    = pSdoInd->SdoHeader.Sdo[SDOHEADER_SUBINDEXOFFSET] >> SDOHEADER_SUBINDEXSHIFT;        /* OBJ_GetObjectHandle checks if the requested index is defined in the object dictionary */
/*OBJ_GetObjectHandle检查是否需要的index是否在对象字典里面定义,并获得它的句柄*/        pObjEntry = OBJ_GetObjectHandle( index );        if ( pObjEntry )        {
    /*如果在搜寻所有的对象字典之后,得到所需要索引的句柄*/            /* 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 */
    /*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 */
    /*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上传请求的话                {
/*如果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 */
/*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 */
/*因为请求的对象数据是小于4个字节,初始化4个字节数据给SDO上传响应*/                        pData[0] = 0;                        pData[1] = 0;                    }                    else//这个else是对应上面的((objLength<=MAX_EXPEDITED_DATA)&& objLength !=0) 如果对象字典的长度大于MAX_EXPEDITED_DATA也就是4个字节的时候。则说明上传是分段上传模式或者是正常上传模式。                    {                    dataSize = u16SendMbxSize - MBX_HEADER_SIZE - UPLOAD_NORM_RES_SIZE;/*如果对象字典的长度比邮箱对象数据区的长度还要打的时候,说明是要采用分段类型的形式上传数据*/                        if ( dataSize < objLength )                            /* Segmented Upload */                            segTransfer = 1;
                        else/*否则采用正常上传模式*/
                            /* Normal Upload */                            pData = ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data;
    /*pData指向对象字典的数据区地址*/#else/*如果从站本身不支持分段上传模式的话,则不需要上面的判断*/                        /* Normal Upload */                        /* pData is the pointer where the object data has to be copied for the response */
/*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 */
   //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 );
//如果读操作成功的话,则返回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 );
//这个函数将会被调用当下载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;}

原创粉丝点击