⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bf_util.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 4 页
字号:
{
   UINT16                        iMappingEntry;
   void                         *pBufferData;
   volatile BF_ActiveEntryType  *psActiveEntry;
   volatile bf_AppDataAreaType  *psAppDataArea;
   volatile bf_MappingEntryType *psMappingEntry;


   GS_UseCritical();

   /*
   ** See if there is a mapping entry associated with the transport ID.
   */

   GS_EnterCritical();
   {
      iMappingEntry = bf_s.aiMappingByTransport[ iTransportId ];

      if( iMappingEntry == BF_NO_MAPPING )
      {
         GS_ExitCritical();
         return FALSE;
      }

      /*
      ** Look up the main mapping entry,
      ** then look up the active list entry via the main entry.
      */

      psMappingEntry = &bf_s.asMappingEntries[ iMappingEntry ];
      psActiveEntry  = &bf_s.asActiveEntries[ psMappingEntry->iActiveEntry ];

      /*
      ** Calculate the pointer to the data portion of the buffer.
      ** This is what actually gets loaded into the active entry.
      ** (There may be status ahead of the data in the buffer...)
      ** Bottom line here is if we're passed a null buffer pointer,
      ** keep it null in all cases.
      */

      if( pTranBuf == NULL )
      {
         pBufferData = NULL;
      }
      else
      {
         pBufferData = (UINT8*)pTranBuf + psActiveEntry->iTranBufOffset;
      }

      /*
      ** Move the resultant pointer to the data into the appropriate
      ** pointer in the active list entry.
      */

      psAppDataArea = &bf_s.asAppDataAreas[ psMappingEntry->eAppDataAreaId ];

      if( psMappingEntry->fCon )
      {
         psActiveEntry->pSource = pBufferData;

         /*
         ** New data to be written into the application data area.
         ** Notify the app data area handler as requested.
         */

         if( psAppDataArea->xSNotifySemaphore != GS_NO_SEMAPHORE )
         {
            GS_SetSemaphore( psAppDataArea->xSNotifySemaphore );
         }
         else
         {
            if( psAppDataArea->xSNotifyQueue != GS_NO_QUEUE )
            {
               GS_PutMsgQueueBits( psAppDataArea->xSNotifyQueue, psAppDataArea->iSNotifyBitMsg );
            }
         }
      }
      else
      {
         /*
         ** New data being read from the application data area.
         */

         psActiveEntry->pDestination = pBufferData;
      }
   }
   GS_ExitCritical();

   return TRUE;
} /* end of BF_UpdateMapping() */



/****************************************************************************
*****************************************************************************
**
** Private Services
**
*****************************************************************************
****************************************************************************/

/*---------------------------------------------------------------------------
** bf_AccessMapping()
**---------------------------------------------------------------------------
*/

void bf_AccessMapping( BF_AccessTrrblType *pTrrbl )
{
   UINT16                         iMappingEntry;
   volatile bf_AppDataAreaType   *psAppDataArea;
   volatile bf_MappingEntryType  *psMappingEntry;

   /*
   ** Make sure we have a valid mapping entry first.
   ** Get a convenience pointer to it if it exists.
   */

   iMappingEntry = bf_FindMapping( pTrrbl->iClass, pTrrbl->iInstance, pTrrbl->fCon );

   if( iMappingEntry == BF_NO_MAPPING )
   {
      pTrrbl->eStatus = BF_NO_SUCH_MAPPING;
      GS_ReturnTrrbl( pTrrbl );
      return;
   }

   psMappingEntry = &bf_s.asMappingEntries[ iMappingEntry ];

   /*
   ** Look up the application memory area this mapping entry uses.
   ** Save it in the access request tribble.
   */

   psAppDataArea = &bf_s.asAppDataAreas[ psMappingEntry->eAppDataAreaId ];
   pTrrbl->eAppDataAreaId     = psMappingEntry->eAppDataAreaId;
   pTrrbl->iAppDataAreaOffset = psMappingEntry->iAppDataAreaOffset;

   /*
   ** Calculate the cpu time for this request.
   ** Saves us from doing it when we're crunched for time trying to
   ** process as many as possible.  Also keeps us from having to
   ** recalculate the cpu time for the first one multiple times if we
   ** just have a little time left to process and skip it several times.
   */

   pTrrbl->lCpuTime = psAppDataArea->lCpuTimePerMessage +
                      psAppDataArea->lCpuTimePerEntry +
                      ( psAppDataArea->lCpuTimePerByte * pTrrbl->iSize );

   /*
   ** If we're supposed to forward the access tribble, do it now.
   */

   if( ( psAppDataArea->xMNotifyQueue != GS_NO_QUEUE ) &&
       ( psAppDataArea->iMNotifyBitMsg == 0 ) )
   {
      GS_PutTrrbl( psAppDataArea->xMNotifyQueue, pTrrbl );
      return;
   }

   /*
   ** No immediate forwarding requested.
   ** Put the request tribble on the access request linked list.
   */

   LL_PutSingleLinkList( (void *)&psAppDataArea->sAccessRequestList, pTrrbl );

   /*
   ** Notify the app data area handler if and as requested.
   */

   if( psAppDataArea->xMNotifySemaphore != GS_NO_SEMAPHORE )
   {
      GS_SetSemaphore( psAppDataArea->xMNotifySemaphore );
   }

   if( psAppDataArea->xMNotifyQueue != GS_NO_QUEUE )
   {
      GS_PutMsgQueueBits( psAppDataArea->xMNotifyQueue, psAppDataArea->iMNotifyBitMsg );
   }

} /* end of bf_AccessMapping() */



/*---------------------------------------------------------------------------
** bf_ActivateMapping()
**---------------------------------------------------------------------------
*/

void bf_ActivateMapping( BF_ActivateTrrblType *pTrrbl )
{
   UINT16                         iActiveEntry;
   UINT16                         iAppDataAreaId;
   UINT16                         iAppDataAreaIdTemp;
   UINT16                         iMappingEntry;
   UINT16                         iSubList;
   UINT16                         iSubListTemp;
   UINT32                         lCpuTime;
   volatile BF_ActiveEntryType   *psActiveEntry;
   volatile bf_ActiveSubListType *psActiveSubList;
   volatile bf_ActiveSubListType *psActiveSubListTemp;
   volatile bf_AppDataAreaType   *psAppDataArea;
   volatile bf_AppDataAreaType   *psAppDataAreaTemp;
   volatile bf_MappingEntryType  *psMappingEntry;


   GS_UseCritical();

   /*
   ** Make sure we have a valid mapping entry first.
   ** Get a convenience pointer to it if it exists.
   */

   iMappingEntry = bf_FindMapping( pTrrbl->iClass, pTrrbl->iInstance, pTrrbl->fCon );

   if( iMappingEntry == BF_NO_MAPPING )
   {
      return;
   }

   psMappingEntry = &bf_s.asMappingEntries[ iMappingEntry ];

   /*
   ** Bail if no reservation has been made.
   */

   if( psMappingEntry->iActiveUsers == 0 )
   {
      return;
   }

   /*
   ** We're done if there's an active entry already in place.
   */

   if( psMappingEntry->iActiveEntry != BF_NO_MAPPING )
   {
	  /*
	  ** start edits: October,28th 2005, H.F.
	  **
	  ** Problem: iTransportId is NOT unique for a Consumer Assembly.
	  **		  If there are 3 class 1 connections to the same Consumer
	  **		  Connection Point, there will also be 3 iTransportIds.
	  **		  However, it is used for mapping entries. So it can happen
	  **		  that the iTransportId, that is currently used for mapping
	  **		  a Consumer Assembly is now used in conjunction with another
	  **		  Consumer Assembly, as the associated connection to the 
	  **		  first Consumer Assembly was closed and so the iTransportId
	  **		  was released and is now used by another connection to the
	  **		  second Consumer Assembly. The mapping of the first Consumer
	  **		  Assembly has been overwritten by the mapping of the second
	  **		  Consumer Assembly, then. And this can result in an Access
	  **		  Violation when closing the connection to the first Consumer
	  **		  Assembly.
	  **
	  ** Workaround: Map the Consumer Connection Point to all of its iTransportIds
	  **			 If the currently actually used iTransportId is released, another
	  **			 iTransportId can then be selected to be used for the actual
	  **			 mapping.
	  */

	  if( psMappingEntry->fCon )
		  bf_s.aiMappingByTransport[ pTrrbl->iTransportId ] = iMappingEntry;

	  /*
	  ** end edits: October,28th 2005, H.F.
	  */

      return;
   }

   /*
   ** Pull out the application memory area info.
   ** Compute the copy time for this entry.
   */

   iAppDataAreaId = psMappingEntry->eAppDataAreaId;
   psAppDataArea  = &bf_s.asAppDataAreas[ iAppDataAreaId ];
   lCpuTime       = psAppDataArea->lCpuTimePerEntry + ( psAppDataArea->lCpuTimePerByte * pTrrbl->iResyncSize );

   /*
   ** Find the first available sub-list that has room,
   ** that is, the penalty is not exceeded.
   */

   iSubList = pTrrbl->fCon ? ( BF_NUM_SUB_LISTS / 2 ) : 0;
   iSubListTemp = BF_NUM_SUB_LISTS / 2;

   while( iSubListTemp &&
          ( ( psAppDataArea->asActiveSubList[ iSubList ].lCpuTimeAreaSubList + lCpuTime ) > psAppDataArea->lCpuTimeMaxResync ) )
   {
      iSubList++;
      iSubListTemp--;
   }

   GS_LogEventIf( iSubListTemp == 0, BF_CPU_TIME_EXCEEDED, iAppDataAreaId, pTrrbl, FATAL );
   psActiveSubList = &psAppDataArea->asActiveSubList[ iSubList ];

   /*
   ** Slide the entries in the active list up to make room.
   ** Start with the highest app mem area and work our way down.
   ** Within each app mem area, handle each active entry sub list separately.
   */

   iAppDataAreaIdTemp = AD_NUM_APP_DATA_AREAS - 1;
   iActiveEntry       = bf_s.iActiveEntries;

   while( iAppDataAreaIdTemp > iAppDataAreaId )
   {
      psAppDataAreaTemp = &bf_s.asAppDataAreas[ iAppDataAreaIdTemp ];

      for( iSubListTemp = BF_NUM_SUB_LISTS; iSubListTemp > 0 ; iSubListTemp-- )
      {
         psActiveSubListTemp = &psAppDataAreaTemp->asActiveSubList[ iSubListTemp - 1 ];

         if( psActiveSubListTemp->iActiveEntries )
         {
            /*
            ** This active sub list has entries.
            ** Move the first entry in this list to
            ** one past the end of this list.
            ** Adjust the starting point of the list.
            */

            GS_EnterCritical();
            {
               bf_MoveActiveEntry( psActiveSubListTemp->iActiveEntry1 + psActiveSubListTemp->iActiveEntries, psActiveSubListTemp->iActiveEntry1 );
               iActiveEntry = psActiveSubListTemp->iActiveEntry1;
               psActiveSubListTemp->iActiveEntry1++;
            }
            GS_ExitCritical();
         }
      }
      iAppDataAreaIdTemp--;
   }

   /*
   ** Room has been made for the newly activated entry.
   ** If this is the first entry for this sub list,
   ** note where the sub list starts.
   */

   if( psActiveSubList->iActiveEntries == 0 )
   {
      psActiveSubList->iActiveEntry1 = iActiveEntry;
   }

   /*
   ** New entry goes in one place past the current end of this
   ** active sub list's entries in the active entry list.
   */

   psActiveEntry = &bf_s.asActiveEntries[ iActiveEntry ];

   psActiveEntry->pSource        =  pTrrbl->fCon ? (UINT8*)pTrrbl->pTranBuf + pTrrbl->iTranBufOffset : (UINT8*)psAppDataArea->pBaseAddress + psMappingEntry->iAppDataAreaOffset;
   psActiveEntry->pDestination   = !pTrrbl->fCon ? (UINT8*)pTrrbl->pTranBuf + pTrrbl->iTranBufOffset : (UINT8*)psAppDataArea->pBaseAddress + psMappingEntry->iAppDataAreaOffset;
   psActiveEntry->iResyncSize    = pTrrbl->iResyncSize;
   psActiveEntry->iTranBufOffset = pTrrbl->iTranBufOffset;
   psActiveEntry->pAddStatus     = pTrrbl->pAddStatus;
   psActiveEntry->iTransportId   = pTrrbl->iTransportId;
   psActiveEntry->iPort          = pTrrbl->iPort;

   /*
   ** Connect the main entry to the transport ID sorted entry.
   ** Connect the main entry to the active entry.
   ** Connect the main entry to the sub-list.
   ** Connect the transport ID sorted entry to the main entry.
   */

   psMappingEntry->iActiveEntry   = iActiveEntry;
   psMappingEntry->iTransportId   = pTrrbl->iTransportId;
   psMappingEntry->iActiveSubList = iSubList;
   bf_s.aiMappingByTransport[ pTrrbl->iTransportId ] = iMappingEntry;

   /*
   ** Bump the total active entry count for the app memory area.
   ** Add to the active sub-list penalty.
   */

   bf_s.iActiveEntries++;
   psActiveSubList->lCpuTimeAreaSubList += lCpuTime;

   GS_EnterCritical();
   {
      psActiveSubList->iActiveEntries++;
   }
   GS_ExitCritical();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -