William Kane / Generic

Dependents:   LaserioLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers abcc_par30_drv.c Source File

abcc_par30_drv.c

00001 /*******************************************************************************
00002 ********************************************************************************
00003 **                                                                            **
00004 ** ABCC Driver version 4.01.01 (2015-12-14)                                   **
00005 **                                                                            **
00006 ** Delivered with:                                                            **
00007 **    ABP         7.16.01 (2015-10-14)                                        **
00008 **                                                                            */
00009 /*******************************************************************************
00010 ********************************************************************************
00011 ** COPYRIGHT NOTIFICATION (c) 2013 HMS Industrial Networks AB                 **
00012 **                                                                            **
00013 ** This code is the property of HMS Industrial Networks AB.                   **
00014 ** The source code may not be reproduced, distributed, or used without        **
00015 ** permission. When used together with a product from HMS, permission is      **
00016 ** granted to modify, reproduce and distribute the code in binary form        **
00017 ** without any restrictions.                                                  **
00018 **                                                                            **
00019 ** THE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. HMS DOES NOT    **
00020 ** WARRANT THAT THE FUNCTIONS OF THE CODE WILL MEET YOUR REQUIREMENTS, OR     **
00021 ** THAT THE OPERATION OF THE CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR     **
00022 ** THAT DEFECTS IN IT CAN BE CORRECTED.                                       **
00023 ********************************************************************************
00024 ********************************************************************************
00025 ** File Description:
00026 ** Parallel (PARI) driver implementation.
00027 ********************************************************************************
00028 ********************************************************************************
00029 */
00030 #include "abcc_drv_cfg.h"
00031 
00032 #if( ABCC_CFG_DRV_PARALLEL_30 )
00033 
00034 #include "abcc_td.h"
00035 #include "../abcc_debug_err.h"
00036 #include "abcc_sys_adapt.h"
00037 #include "../abcc_timer.h"
00038 #include "../abcc_drv_if.h"
00039 #include "../abcc_mem.h"
00040 #include "abp.h"
00041 #include "abcc_sys_adapt_par.h"
00042 #include "abcc_port.h"
00043 
00044 /*******************************************************************************
00045 ** Constants
00046 ********************************************************************************
00047 */
00048 
00049 /*******************************************************************************
00050 ** Typedefs
00051 ********************************************************************************
00052 */
00053 
00054 typedef enum ABCC_DrvPar30State
00055 {
00056    SM_RDY_TO_PING,
00057    SM_WAITING_FOR_PONG,
00058    SM_SER_INIT
00059 }
00060 ABCC_DrvPar30StateType;
00061 
00062 /*******************************************************************************
00063 ** Private Globals
00064 ********************************************************************************
00065 */
00066 
00067 static ABP_MsgType* par_drv_pbReadMessageData;
00068 static  UINT8* par_drv_pbRdPdBuffer;
00069 
00070 static UINT16   par_drv_iSizeOfReadPd;
00071 static UINT16   par_drv_iSizeOfWritePd;
00072 
00073 static   UINT8    par_drv_bNbrOfCmds;          /* Number of commands supported by the application. */
00074 static ABCC_TimerHandle xWdTmoHandle;
00075 static BOOL  fWdTmo;                          /* Current wd timeout status */
00076 static BOOL drv_fLegacy;                      /* USe legacy format         */
00077 
00078 /*
00079 ** Working copies of the status and control registers
00080 */
00081 static volatile UINT8   bControlReg = ABP_CTRL_R_BIT;
00082 static volatile UINT8   bStatusReg  = 0x80;
00083 static volatile ABCC_DrvPar30StateType eState = SM_SER_INIT;
00084 
00085 
00086 
00087 /*******************************************************************************
00088 ** Private forward declarations
00089 ********************************************************************************
00090 */
00091 
00092 
00093 /*******************************************************************************
00094 ** Private Services
00095 ********************************************************************************
00096 */
00097 /*
00098 ** Converting to/from legacy message format.
00099 **
00100 **  ABCC40 msg header      Leagcy msg header
00101 ** --------------------
00102 ** | UINT16 iDataSize |
00103 ** --------------------
00104 ** | UINT16 iReserved |
00105 ** --------------------    --------------------
00106 ** | UINT8 bSourceId  |    | UINT8 bSourceId  |
00107 ** --------------------    --------------------
00108 ** | UINT8 bDestObj   |    | UINT8 bDestObj   |
00109 ** --------------------    --------------------
00110 ** | UINT8 bSourceId  |    | UINT8 bSourceId  |
00111 ** --------------------    --------------------
00112 ** | UINT16 iInstance |    | UINT16 iInstance |
00113 ** --------------------    --------------------
00114 ** | UINT8 bReserved  |    | UINT8 bDataSize  |
00115 ** --------------------    --------------------
00116 ** | UINT8 bCmdExt0   |    | UINT8 bCmdExt0   |
00117 ** --------------------    --------------------
00118 ** | UINT8 bCmdExt1   |    | UINT8 bCmdExt1   |
00119 ** --------------------    --------------------
00120 **
00121 ** The last 8 bytes in the new message format
00122 ** structured the same way as the legacy message format
00123 ** except for bReserved which is placed on the legacy
00124 ** bDataSize position.
00125 **
00126 ** This means that the conversion from "new" meessage format
00127 ** to legacy format
00128 ** is simply done by copying the iDataSize to the bReserved
00129 ** filed and the message is sent from the bsourceId address position.
00130 **
00131 **
00132 ** Read message are converted the same way. The data from
00133 ** ACI are copied to the bSourceId address position. The bReserved
00134 ** field are copied to the iDataSize filed.
00135 **
00136 ** Note that the iDataSize need to be converted to/from little endian.
00137 **
00138 */
00139 static void drv_DoMsgWrite( ABP_MsgType* psMsg )
00140 {
00141    /*
00142    ** First Calculate total message size
00143    */
00144    UINT16 iMsgSize = iLeTOi( psMsg->sHeader.iDataSize );
00145 
00146    ABCC_ASSERT( iMsgSize < ABP_MAX_MSG_DATA_BYTES );
00147    iMsgSize += sizeof( ABP_MsgHeaderType );
00148 
00149    ABCC_DrvParallelWrite( ABP_WRMSG_ADR_OFFSET, (UINT8*)psMsg, iMsgSize );
00150 }
00151 
00152 
00153 static void drv_DoLegacyMsgWrite( ABP_MsgType* psMsg )
00154 {
00155    UINT16 iMsgSize = iLeTOi( psMsg->sHeader.iDataSize );
00156 
00157    ABCC_ASSERT( iMsgSize <= ABP_MAX_MSG_255_DATA_BYTES );
00158    iMsgSize += sizeof( ABP_Msg255HeaderType );
00159    psMsg->sHeader.bReserved = (UINT8)psMsg->sHeader.iDataSize;
00160    ABCC_DrvParallelWrite( ABP_WRMSG_LEGACY_ADR_OFFSET, (UINT8*)&psMsg->sHeader.bSourceId, iMsgSize );
00161 }
00162 
00163 static void drv_DoMsgRead( ABP_MsgType* psMsg )
00164 {
00165    UINT16 iMsgSize;
00166 
00167    ABCC_DrvParallelRead( ABP_RDMSG_ADR_OFFSET, (UINT8*)psMsg, sizeof( ABP_MsgHeaderType ) );
00168 
00169    iMsgSize = iLeTOi( psMsg->sHeader.iDataSize );
00170 
00171    if( iMsgSize > ABCC_CFG_MAX_MSG_SIZE )
00172    {
00173       /*
00174       ** Message size exceeds buffer.
00175       */
00176       ABCC_ERROR( ABCC_SEV_FATAL, ABCC_EC_RDMSG_SIZE_ERR, 0 );
00177 
00178       return;
00179    }
00180 
00181    /*
00182    ** Continue reading data area if > 0.
00183    */
00184    if ( iMsgSize > 0 )
00185    {
00186       ABCC_DrvParallelRead( ABP_RDMSG_ADR_OFFSET + sizeof( ABP_MsgHeaderType ),
00187                             psMsg->abData,
00188                             iMsgSize );
00189    }
00190 }
00191 
00192 
00193 void drv_DoLegacyMsgRead( ABP_MsgType* psMsg )
00194 {
00195    UINT16 iMsgSize;
00196 
00197    ABCC_DrvParallelRead( ABP_RDMSG_LEGACY_ADR_OFFSET, (UINT8*)&psMsg->sHeader.bSourceId, sizeof( ABP_Msg255HeaderType ) );
00198 
00199    iMsgSize = (UINT16)( psMsg->sHeader.bReserved );
00200 
00201    if( ( iMsgSize > ABP_MAX_MSG_255_DATA_BYTES ) ||
00202        ( iMsgSize > ABCC_CFG_MAX_MSG_SIZE ) )
00203    {
00204       /*
00205       ** Message size exceeds buffer.
00206       */
00207       ABCC_ERROR( ABCC_SEV_FATAL, ABCC_EC_RDMSG_SIZE_ERR, 0 );
00208 
00209       return;
00210    }
00211 
00212    psMsg->sHeader.iDataSize = iTOiLe( iMsgSize );
00213 
00214    /*
00215    ** Continue reading data area if > 0.
00216    */
00217    if( iMsgSize > 0 )
00218    {
00219       ABCC_DrvParallelRead( ABP_RDMSG_LEGACY_ADR_OFFSET + sizeof( ABP_Msg255HeaderType ),
00220                             psMsg->abData,
00221                             iMsgSize );
00222    }
00223 }
00224 
00225 
00226 static void drv_WdTimeoutHandler( void )
00227 {
00228    fWdTmo = TRUE;
00229    ABCC_CbfWdTimeout();
00230 }
00231 
00232 /*******************************************************************************
00233 ** Public Services
00234 ********************************************************************************
00235 */
00236 void ABCC_DrvPar30Init( UINT8 bOpmode )
00237 {
00238    /*
00239    ** Initialize privates and states.
00240    */
00241    ABCC_ASSERT_ERR( bOpmode == 8 , ABCC_SEV_FATAL, ABCC_EC_INCORRECT_OPERATING_MODE, (UINT32)bOpmode );
00242 
00243    par_drv_iSizeOfReadPd  = 0;
00244    par_drv_iSizeOfWritePd = 0;
00245    par_drv_bNbrOfCmds     = 0;
00246    par_drv_pbRdPdBuffer = ABCC_DrvParallelGetRdPdBuffer();
00247    bControlReg = ABP_CTRL_R_BIT | ABP_CTRL_T_BIT;
00248    bStatusReg  = 0;
00249    eState = SM_SER_INIT;
00250    xWdTmoHandle = ABCC_TimerCreate( drv_WdTimeoutHandler );
00251    fWdTmo = FALSE;
00252 
00253    /* If an ABCC40 is attached then use big messages */
00254    if ( ABCC_ReadModuleId() == ABP_MODULE_ID_ACTIVE_ABCC40 )
00255    {
00256       drv_fLegacy = FALSE;
00257    }
00258    else
00259    {
00260       drv_fLegacy = TRUE;
00261    }
00262 }
00263 
00264 void ABCC_DrvPar30SetIntMask( const UINT16 iIntMask )
00265 {
00266  /*
00267   ** Not possible to set interrupt mask.
00268   */
00269  (void)iIntMask;
00270 }
00271 
00272 #if( ABCC_CFG_INT_ENABLED )
00273 UINT16 ABCC_DrvPar30ISR( void )
00274 {
00275    /*
00276     ** Interrupt is acknowledged when status register is read
00277     */
00278    ABCC_DrvRead8( ABP_STATUS_ADR_OFFSET );
00279 
00280    return 0;
00281 }
00282 #else
00283 UINT16 ABCC_DrvPar30ISR( void )
00284 {
00285    ABCC_ERROR( ABCC_SEV_WARNING, ABCC_EC_INTERNAL_ERROR, 0);
00286    return 0;
00287 }
00288 #endif
00289 
00290 
00291 ABP_MsgType* ABCC_DrvPar30RunDriverRx( void )
00292 {
00293    UINT8 bNewStatusReg1;
00294    UINT8 bNewStatusReg2;
00295 
00296    if ( eState == SM_WAITING_FOR_PONG )
00297    {
00298 
00299       do
00300       {
00301           bNewStatusReg1 = ABCC_DrvRead8( ABP_STATUS_ADR_OFFSET );
00302           bNewStatusReg2 = ABCC_DrvRead8( ABP_STATUS_ADR_OFFSET );
00303       } while ( bNewStatusReg1 != bNewStatusReg2 );
00304 
00305 
00306       if( ( bNewStatusReg1 & ABP_STAT_T_BIT ) != ( bStatusReg & ABP_STAT_T_BIT ) )
00307       {
00308           bStatusReg = bNewStatusReg1;
00309           bControlReg &= ~ABP_CTRL_M_BIT;
00310           bControlReg ^= ABP_CTRL_T_BIT;
00311 
00312           ABCC_TimerStop( xWdTmoHandle );
00313           /*
00314            ** Check if timeout has occurred.
00315            */
00316           if( fWdTmo == TRUE )
00317           {
00318              ABCC_CbfWdTimeoutRecovered();
00319           }
00320           fWdTmo = FALSE;
00321           eState = SM_RDY_TO_PING;
00322       }
00323    }
00324    else if ( eState == SM_SER_INIT )
00325    {
00326       eState = SM_RDY_TO_PING;
00327    }
00328 
00329    return NULL;
00330 }
00331 
00332 
00333 void ABCC_DrvPar30RunDriverTx( void )
00334 {
00335    if(eState == SM_RDY_TO_PING )
00336     {
00337        ABCC_DrvWrite8( ABP_CONTROL_ADR_OFFSET, bControlReg );
00338        /*
00339        ** Start WD timer
00340        */
00341        ABCC_TimerStart(xWdTmoHandle, ABCC_CFG_WD_TIMEOUT_MS );
00342        eState = SM_WAITING_FOR_PONG;
00343     }
00344 }
00345 
00346 
00347 
00348 
00349 BOOL ABCC_DrvPar30WriteMessage( ABP_MsgType* psWriteMsg )
00350 {
00351    ABCC_ASSERT( psWriteMsg );
00352 
00353    if( drv_fLegacy )
00354    {
00355      drv_DoLegacyMsgWrite( psWriteMsg );
00356    }
00357    else
00358    {
00359       drv_DoMsgWrite( psWriteMsg );
00360    }
00361 
00362    bControlReg |= ABP_CTRL_M_BIT;
00363 
00364    /*
00365    ** Determine if command messages (instead of response messages) can be sent.
00366    */
00367    if( !( psWriteMsg->sHeader.bCmd & ABP_MSG_HEADER_C_BIT ) )
00368    {
00369       /*
00370       ** A command message has been received by the host application and a
00371       ** response message (not a command message) will be sent back to the
00372       ** Anybus. The number of commands the host application can receive
00373       ** shall be increased by one, as a previous received command is now
00374       ** handled.
00375       */
00376       par_drv_bNbrOfCmds++;
00377 
00378       /*
00379       ** When a change of the number of commands which the host application
00380       ** can receive is made from 0 to 1, it means that we can set the APPRF
00381       ** flag again to indicate for the Anybus that the host is now ready to
00382       ** receive a new command.
00383       */
00384        bControlReg |= ABP_CTRL_R_BIT;;
00385    }
00386 
00387    /*
00388    ** Update the buffer control register.
00389    */
00390     return( TRUE);
00391 }
00392 
00393 
00394 void ABCC_DrvPar30WriteProcessData( void* pxProcessData )
00395 {
00396 
00397    if(  par_drv_iSizeOfWritePd )
00398    {
00399       /*
00400       ** Write process data.
00401       */
00402       ABCC_DrvWriteWrPd(pxProcessData, par_drv_iSizeOfWritePd );
00403    }
00404 }
00405 
00406 
00407 BOOL ABCC_DrvPar30IsReadyForWriteMessage( void )
00408 {
00409    BOOL fRdyForCmd =  FALSE;
00410 
00411    if( eState == SM_RDY_TO_PING  )
00412    {
00413       if( !( bControlReg & ABP_CTRL_M_BIT ) )
00414       {
00415          fRdyForCmd = TRUE;
00416       }
00417    }
00418    return fRdyForCmd;
00419 }
00420 
00421 
00422 BOOL ABCC_DrvPar30IsReadyForCmd( void )
00423 {
00424    BOOL fRdyForCmd =  FALSE;
00425 
00426    if( eState == SM_RDY_TO_PING )
00427    {
00428       if( ( bStatusReg & ABP_STAT_R_BIT ) && !( bControlReg & ABP_CTRL_M_BIT ) )
00429       {
00430          fRdyForCmd = TRUE;
00431       }
00432    }
00433 
00434    return fRdyForCmd;
00435 }
00436 
00437 
00438 void ABCC_DrvPar30SetNbrOfCmds( UINT8 bNbrOfCmds )
00439 {
00440    par_drv_bNbrOfCmds = bNbrOfCmds;
00441 
00442    /*
00443    ** Acknowledge that we are ready to accept the first command message.
00444    */
00445    bControlReg |= ABP_CTRL_R_BIT;
00446 }
00447 
00448 
00449 void ABCC_DrvPar30SetAppStatus( ABP_AppStatusType eAppStatus )
00450 {
00451    (void)eAppStatus;
00452 }
00453 
00454 void ABCC_DrvPar30SetPdSize( const UINT16 iReadPdSize, const UINT16 iWritePdSize )
00455 {
00456    par_drv_iSizeOfReadPd = iReadPdSize;
00457    par_drv_iSizeOfWritePd = iWritePdSize;
00458 }
00459 
00460 
00461 static void DrvPar30SetMsgReceiverBuffer( ABP_MsgType* const psReadMsg )
00462 {
00463    /*
00464    ** The buffer can be NULL if we are out of msg resources.
00465    ** We can not start a new ping-pong before this is resolved.
00466    */
00467    par_drv_pbReadMessageData = psReadMsg;
00468 }
00469 
00470 
00471 UINT16 ABCC_DrvPar30GetIntStatus( void )
00472 {
00473    return  0;
00474 }
00475 
00476 UINT8 ABCC_DrvPar30GetAnybusState( void )
00477 {
00478    /*
00479    ** The Anybus state is stored in bits 0-2 of the status register.
00480    */
00481    return( bStatusReg & 0x07 );
00482 }
00483 
00484 
00485 void* ABCC_DrvPar30ReadProcessData( void )
00486 {
00487    /*
00488     ** TODO Check valid data
00489     */
00490 
00491    if ( ( par_drv_iSizeOfReadPd == 0)  || ( eState  == SM_WAITING_FOR_PONG ) )
00492    {
00493       return NULL;
00494    }
00495 
00496    ABCC_DrvReadRdPd( par_drv_pbRdPdBuffer, par_drv_iSizeOfReadPd );
00497    return( par_drv_pbRdPdBuffer );
00498 }
00499 
00500 ABP_MsgType* ABCC_DrvPar30ReadMessage( void )
00501 {
00502    if( eState == SM_RDY_TO_PING )
00503    {
00504       if( bStatusReg & ABP_STAT_M_BIT  )
00505       {
00506          DrvPar30SetMsgReceiverBuffer( ABCC_MemAlloc() );
00507 
00508          if( par_drv_pbReadMessageData == NULL )
00509          {
00510             ABCC_ERROR( ABCC_SEV_WARNING, ABCC_EC_OUT_OF_MSG_BUFFERS, 0 );
00511             return( NULL );
00512          }
00513 
00514          if( drv_fLegacy )
00515          {
00516            drv_DoLegacyMsgRead( par_drv_pbReadMessageData );
00517          }
00518          else
00519          {
00520             drv_DoMsgRead( par_drv_pbReadMessageData );
00521          }
00522 
00523          /*
00524          ** Determine if command messages (instead of response messages) can be read.
00525          */
00526          if( par_drv_pbReadMessageData->sHeader.bCmd & ABP_MSG_HEADER_C_BIT )
00527          {
00528             /*
00529             ** A command messages has been sent by the Anybus and it has been read
00530             ** by the host application. The number of commands allowed by the host
00531             ** application must be decreased by one.
00532             */
00533             par_drv_bNbrOfCmds--;
00534 
00535             /*
00536             ** Indicates that the host application is not ready to receive a new
00537             ** command from the Anybus. Writing to this register must only be done
00538             ** when the RDMSG bit is set to 1. A check is not required however,
00539             ** since the RDMSG bit is set to 1 a few lines higher up in the code.
00540             */
00541             if( par_drv_bNbrOfCmds == 0 )
00542             {
00543                /*
00544                ** Update the buffer control register.
00545                */
00546                bControlReg &= ~ABP_CTRL_R_BIT;
00547             }
00548          }
00549 
00550          return( par_drv_pbReadMessageData );
00551       }
00552    }
00553    return( NULL );
00554 }
00555 
00556 BOOL ABCC_DrvPar30IsReadyForWrPd( void )
00557 {
00558    if ( eState == SM_RDY_TO_PING )
00559    {
00560       return TRUE;
00561    }
00562 
00563    return FALSE;
00564 }
00565 
00566 UINT8* ABCC_DrvPar30GetWrPdBuffer( void )
00567 {
00568    return ABCC_DrvParallelGetWrPdBuffer();
00569 }
00570 
00571 
00572 UINT16 ABCC_DrvPar30GetModCap( void )
00573 {
00574    return 0xFFFF;
00575 }
00576 
00577 UINT16 ABCC_DrvPar30GetLedStatus( void )
00578 {
00579    return 0;
00580 }
00581 
00582 BOOL ABCC_DrvPar30IsSupervised( void )
00583 {
00584    /*
00585    ** The Anybus supervision bis is stored in bit 3
00586    */
00587    return( ( bStatusReg >> 3 ) & 1 );
00588 }
00589 
00590 UINT8 ABCC_DrvPar30GetAnbStatus( void )
00591 {
00592    return bStatusReg & 0xf ;
00593 }
00594 
00595 
00596 
00597 #endif
00598 /*******************************************************************************
00599 ** End of par_drv.c
00600 ********************************************************************************
00601 */