MBX_Main()

来源:互联网 发布:海康ntp服务器地址端口 编辑:程序博客网 时间:2024/06/07 00:55
[cpp] view plain copy
  1. /////////////////////////////////////////////////////////////////////////////////////////  
  2. /** 
  3.  \brief    这个函数被周期性得检查,看邮箱服务是否已经有存储 
  4. *////////////////////////////////////////////////////////////////////////////////////////  
  5.   
  6. void MBX_Main(void)  
  7. {  
  8. #if MAILBOX_QUEUE  
  9.     TMBX MBXMEM *pMbx = NULL;  
  10.   
  11.     do  
  12.     {  
  13.         UINT8 result = 0;  
  14.   
  15.         pMbx = GetOutOfMbxQueue(&sMbxReceiveQueue);//在邮箱队列里面获得一个邮箱服务  
  16.         if ( pMbx )  
  17.             result = MailboxServiceInd(pMbx);<span style="white-space:pre"> </span>   //根据获得的邮箱服务调用对应的邮箱服务程序  
  18.   
  19.         if ( result != 0 )  
  20.         {  
  21.             /* 邮箱错误响应:type0(邮箱服务协议) */  
  22.             pMbx->MbxHeader.Length     = 4;  
  23.             pMbx->MbxHeader.Flags[MBX_OFFS_TYPE]        &= ~(MBX_MASK_TYPE);  
  24.             pMbx->Data[0]                        = SWAPWORD(MBXSERVICE_MBXERRORCMD);  
  25.             pMbx->Data[1]                        = SWAPWORD(result);  
  26.             MBX_MailboxSendReq(pMbx, 0);<span style="white-space:pre">  </span>//邮箱错误命令返回主站  
  27.         }  
  28.     }  
  29.     while ( pMbx != NULL );//当邮箱里面多有的服务请求处理完,就跳出来  
  30.   
  31. #endif // MAILBOX_QUEUE  
  32.   
  33.       if ( bReceiveMbxIsLocked )  
  34.       {  
  35.           /* 接受邮箱的工作是被锁,检查是否它可以被解锁(如果所有的邮箱服务已经被发送)t */  
  36.           MBX_CheckAndCopyMailbox();  
  37.       }  
  38. }  
  39.   
  40. #endif //#if MAILBOX_SUPPORTED  





[cpp] view plain copy
  1. ///////////////////////////////////////////////////////////////////////////////////////////  
  2. //  
  3. //    GetOutOfMbxQueue  
  4. //  
  5. //////////////////////////////////////////////////////////////////////////////////////////  
[cpp] view plain copy
  1. //brief  这个函数从接收邮箱的队列里面获得邮箱数据  
[cpp] view plain copy
  1. //return 将邮箱里面第一个邮箱数据返回  
  2. TMBX MBXMEM * GetOutOfMbxQueue(TMBXQUEUE MBXMEM * pQueue)  
  3. {  
  4.     TMBX MBXMEM * pMbx;  
  5.     ENTER_MBX_CRITICAL;  
  6.   
  7.     if (pQueue->firstInQueue != pQueue->lastInQueue)//如果队列里面第一个队列不等于最后一个队列  
  8.     {  
  9.         //获得队列里面第一个队列  
  10.         UINT16 firstInQueue = pQueue->firstInQueue;  
  11.         pMbx = pQueue->queue[firstInQueue++];  
  12.         pQueue->firstInQueue = firstInQueue;  
  13.         if (pQueue->firstInQueue == pQueue->maxQueueSize)//如果第一队列已经到了最大的队列长度  
  14.         {  
  15.             // 将队列链表解除  
  16.             pQueue->firstInQueue = 0;  
  17.         }  
  18.     }  
  19.     else  
  20.         pMbx = 0;  
  21.   
  22.   
  23.     LEAVE_MBX_CRITICAL;  
  24.   
  25.     return pMbx;  
  26. }  



[cpp] view plain copy
  1. /////////////////////////////////////////////////////////////////////////////////////////  
  2. /** 
  3.  \param     pMbx        指向从主站获得的邮箱服务. 
  4.  
  5.  \brief    这个函数检查邮箱头给请求的服务,然后调用对应的XXXX_ServiceInd-function函数 
  6. *////////////////////////////////////////////////////////////////////////////////////////  
  7.   
  8. UINT8 MailboxServiceInd(TMBX MBXMEM *pMbx)  
  9. {  
  10.     UINT8 result;  
  11.   
  12. #if BOOTSTRAPMODE_SUPPORTED  
  13.     /*在Boot模式当中,只有FoE支持*/  
  14.     if(bBootMode == TRUE && (MBX_TYPE_FOE != ((pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] & MBX_MASK_TYPE) >> MBX_SHIFT_TYPE )))  
  15.         return MBXERR_UNSUPPORTEDPROTOCOL;  
  16. #endif  
  17.   
  18.     switch ( (pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] & MBX_MASK_TYPE) >> MBX_SHIFT_TYPE )  
  19.     {  
  20. #if COE_SUPPORTED  
  21.     case MBX_TYPE_COE:  
  22.         /* CoE datagram received */  
  23.         result = COE_ServiceInd((TCOEMBX MBXMEM *) pMbx);  
  24.         break;  
  25.   
  26. #endif  
  27. #if EOE_SUPPORTED  
  28.     case MBX_TYPE_EOE:  
  29.         /* EoE datagram received */  
  30.         result = EOE_ServiceInd(pMbx);  
  31.         break;  
  32. #endif /* EOE_SUPPORTED */  
  33. #if FOE_SUPPORTED  
  34.     case MBX_TYPE_FOE:  
  35.         /* FoE datagram received */  
  36.         result = FOE_ServiceInd((TFOEMBX MBXMEM *) pMbx);  
  37.         break;  
  38.   
  39. #endif /* FOE_SUPPORTED */  
  40. #if VOE_SUPPORTED  
  41.     case MBX_TYPE_VOE:  
  42.         /* VoE datagram received */  
  43.         result = VOE_ServiceInd((TVOEMBX MBXMEM *) pMbx);  
  44.         break;  
  45.   
  46. #endif /* VOE_SUPPORTED */  
  47.     default:  
  48.   
  49.         result = MBXERR_UNSUPPORTEDPROTOCOL;  
  50.         break;  
  51.     }  
  52.   
  53.     return result;  
  54. }  



[cpp] view plain copy
  1. /////////////////////////////////////////////////////////////////////////////////////////  
  2. /** 
  3.  \param     pCoeMbx      指向接收到的从主站过来的邮箱数据 
  4.  
  5.  
  6.  \return    返回的result如果是0,则表示操作成功或者返回邮箱错误代码,在mailbox.h里面定义的 
  7.  
  8.  
  9.  \brief    这个函数被调用当CoE服务从主站里接受到 
  10. *////////////////////////////////////////////////////////////////////////////////////////  
[cpp] view plain copy
  1. UINT8 COE_ServiceInd(TCOEMBX MBXMEM *pCoeMbx)  
  2. {  
  3.     UINT8 result = 0;  
  4.   
  5.     switch ((pCoeMbx->CoeHeader & COEHEADER_COESERVICEMASK) >> COEHEADER_COESERVICESHIFT)  
  6.     {  
  7.     case COESERVICE_SDOREQUEST:  
  8.         /* SDP请求接收,调用SDO_SdoInd函数来处理SDO请求,如果有一个存在的SDO协议栈应该被调用,对应的响应函数应该被调用 */  
  9.         result = SDOS_SdoInd( (TINITSDOMBX MBXMEM *) pCoeMbx );  
  10.         break;  
  11.   
  12.     case COESERVICE_SDOINFO:  
  13.         /* SDO信息请求接收到,调用SDOS_SdoInfoInd函数来处理SDO请求 */  
  14.         result = SDOS_SdoInfoInd( (TSDOINFORMATION MBXMEM *) pCoeMbx );  
  15.         /*NOERROR_INWORK is never returned by SDOS_SdoInfoInd() => delete return code handling*/  
  16.         break;  
  17.   
  18.     case COESERVICE_EMERGENCY:  
  19.     case COESERVICE_SDORESPONSE:  
  20.     case COESERVICE_TXPDO:  
  21.     case COESERVICE_RXPDO:  
  22.     case COESERVICE_TXPDOREMREQ:  
  23.     case COESERVICE_RXPDOREMREQ:  
  24.         /* these CoE services are not supported yet */  
  25.         result = MBXERR_SERVICENOTSUPPORTED;  
  26.         break;  
  27.   
  28.     default:  
  29.         result = MBXERR_INVALIDHEADER;  
  30.         break;  
  31.     }  
  32.     return result;  
  33. }  
注意,上面COE_ServiceInd函数指示定义了COE服务类型里面的SDO请求的处理,而没有定义SDO响应
[cpp] view plain copy
  1. COE_ServiceInd  

从书中P99,CoE服务类型,

0:保留

1:紧急事件信息

2:SDO请求

3:SDO响应

4:TxPDO

5:RxPDO

6:远程TXPDO发送请求

7:远程RxPDO发送请求

8:SDO信息

9~15:保留



[cpp] view plain copy
  1. /////////////////////////////////////////////////////////////////////////////////////////  
  2. /** 
  3.  \brief    这个函数用来检查是否接收邮箱命令可以被处理,和接收邮箱的内容将会被拷贝到对应的变量sMbx 
  4. *////////////////////////////////////////////////////////////////////////////////////////  
  5.   
  6. void MBX_CheckAndCopyMailbox( void )  
  7. {  
  8.     UINT16 mbxLen;  
  9.   
  10.     /* 获得接收邮箱命令的大小和相应对应的事件*/  
  11.     HW_EscReadWord(mbxLen,u16EscAddrReceiveMbx);  
  12.       
  13.     /* 所有的长度应该在这里被转换, 所有邮箱服务里的其它字节将接着被转换 */  
  14.     mbxLen = SWAPWORD(mbxLen);  
  15.   
  16.     /* 邮箱数据的长度是在邮箱开头的两个字节,所以,含有长度的邮箱头应该被加入到里面 */  
  17.     mbxLen += MBX_HEADER_SIZE;  
  18.   
  19.     /* 在这个例子里面只有两个邮箱缓存可用在固件里面(一个是给处理,一个是给储存一个可能重复的请求),因此,一个接收邮箱服务可以被处理,如果空闲的缓存是可用的 */  
  20.     if ( ( bSendMbxIsFull )                /* 一个接收邮箱服务将不会被处理,当发送邮箱仍是满的(等待主站的读操作) */  
  21.         ||( u8MailboxSendReqStored )    /* 一个发送的邮箱服务仍被存储,所以,接收邮箱服务不能被处理,当所有存储的邮箱服务全部被发送 */  
  22.         )  
  23.     {  
  24.         /* 设置符号位,处理邮箱服务将会被检查在函数MBX_Main(在函数ECAT_Main里面被调用) */  
  25.         bReceiveMbxIsLocked = TRUE;  
  26.     }  
  27.     else  
  28.     {   /* 接收邮箱命令可以被处理,重置flag */  
  29.         bReceiveMbxIsLocked = FALSE;  
  30.         /* 如果读邮箱长度是对缓存来说太大,设置拷贝大小给最长的缓存大小,否则,内存将会被覆盖,邮箱的评估将会被处理在邮箱服务MBX_WriteMailboxInd() */  
  31.         if (mbxLen > MBX_BUFFER_SIZE)  
  32.             mbxLen = MBX_BUFFER_SIZE;  
  33.   
  34.         psWriteMbx = (TMBX MBXMEM *) APPL_AllocMailboxBuffer(MBX_BUFFER_SIZE);  
  35.   
  36.         /* 如果没有更多的内存给邮箱缓存,这个邮箱不应该被读 */  
  37.         if (psWriteMbx == NULL)  
  38.         {  
  39.             /* 设置flag以致邮箱服务的处理不应该被检查在函数MBX_Main(由ECAT_Main中调用) */  
  40.             bReceiveMbxIsLocked = TRUE;  
  41.             return;  
  42.         }  
  43.   
  44.         /*读控制和状态SM0的,来检查是否buffer是没有锁的*/  
  45.         VARVOLATILE UINT8 smstate = 0x00;  
  46.         HW_EscReadByte(smstate,ESC_SYNCMAN_STATUS_OFFSET);  
  47.   
  48.         if(smstate & SM_STATUS_MBX_BUFFER_FULL)  
  49.         {  
  50.             u8dummy = 0;  
  51.             HW_EscReadByte(u8dummy,(u16EscAddrReceiveMbx + u16ReceiveMbxSize - 1));  
  52.   
  53.         }  
  54.   
  55.         }  
  56.   
  57.         /* 在函数MBX_MailboxWriteInd,邮箱协议将会被处理 */  
  58.         MBX_MailboxWriteInd( psWriteMbx );  
  59.   
  60.     }  
  61. }  





[cpp] view plain copy
  1. /////////////////////////////////////////////////////////////////////////////////////////  
  2. /** 
  3.  \param     pMbx        指向来自主站的接收邮箱的指针. 
  4.  
  5.  \brief    当主站写接收邮箱的时候,这个函数将会被调用. 
  6.  \brief   它只会被调用,如果发送邮箱是空的时候,邮箱服务的响应将会被存储  
  7.  \brief    这个函数检查邮箱头给需要的服务和调用对应的XXXX_ServiceInd-function 
  8. *////////////////////////////////////////////////////////////////////////////////////////  
  9.   
  10. void MBX_MailboxWriteInd(TMBX MBXMEM *pMbx)  
  11. {  
  12.     UINT8 result = 0;  
  13.     UINT8 mbxCounter = pMbx->MbxHeader.Flags[MBX_OFFS_COUNTER] >> MBX_SHIFT_COUNTER;  
  14. /* ECATCHANGE_START(V5.01) MBX2*/  
  15.     UINT16 MbxLen = SWAPWORD(pMbx->MbxHeader.Length);  
  16.   
  17.     if(MbxLen > MBX_BUFFER_SIZE)  
  18.     {  
  19.         /* 邮箱响应错误:邮箱头的长度太长*/  
  20.         pMbx->MbxHeader.Length     = 4;  
  21.         pMbx->MbxHeader.Flags[MBX_OFFS_TYPE]        &= ~MBX_MASK_TYPE;  
  22.         pMbx->Data[0]                        = SWAPWORD(MBXSERVICE_MBXERRORCMD);  
  23.         pMbx->Data[1]                        = SWAPWORD(MBXERR_INVALIDSIZE);  
  24.         MBX_MailboxSendReq(pMbx, 0);  
  25.     }  
  26. /* ECATCHANGE_END(V5.01) MBX2*/  
  27.     else  
  28.     /* 如果邮箱数据包计数器(邮箱头的第五个字节位4-6)是不等于0,主站支持邮箱数据链路层,在这种情况重复邮箱写请求将被检测,如果计数器是不等于0和不变 */  
  29.     if ( mbxCounter == 0 || mbxCounter != u8MbxWriteCounter )  
  30.     {  
  31.         /* 一个新的邮箱服务接收到 */  
  32.         /* 如果mbxCounter = 0: old EtherCAT master */  
  33.         /* 一个新的MBX服务接收到,保存新的邮箱计数器 */  
  34.         u8MbxWriteCounter = mbxCounter;  
  35.         /* 检查一个协议类型和调用对应的XXXX_ServiceInd-函数 */  
  36.         result = PutInMbxQueue(pMbx, &sMbxReceiveQueue);  
  37.   
  38.         if ( result != 0 )  
  39.         {  
  40.             /* 邮箱错误响应:类型0 */  
  41.             pMbx->MbxHeader.Length     = 4;  
  42.             pMbx->MbxHeader.Flags[MBX_OFFS_TYPE]        &= ~MBX_MASK_TYPE;  
  43.             pMbx->Data[0]                        = SWAPWORD(MBXSERVICE_MBXERRORCMD);  
  44.             pMbx->Data[1]                        = SWAPWORD(result);  
  45.             MBX_MailboxSendReq(pMbx, 0);  
  46.         }  
  47.     }  
  48.     else  
  49.     {  
  50.         APPL_FreeMailboxBuffer(pMbx);  
  51.         pMbx = NULL;  
  52.     }  
  53. }  
0 0
原创粉丝点击